# base_suivis

La base de donnees du client : ce qu'elle contient, et la couche de travail posee dessus. TROIS TYPES : entreprise (ecran Concurrence), acheteur public (ecran Acheteurs), projet detecte (ecran Projets). PRESENCE — action list / add / remove. Identifiant selon le type : entreprise -> siren OU siret OU entreprise_id ; acheteur -> siret OU acheteur_id ; projet -> projet_id. Une entreprise absente de l'annuaire s'ajoute par `nom` (+ `ville`), en fiche hors referentiel. COUCHE DE TRAVAIL, sur une fiche deja dans la base — action qualifier (statut prospect/client/a_qualifier/concurrent, ou null pour l'effacer ; entreprises seulement), etiqueter (`tag`, + `retirer:true` pour l'oter), noter (`note`, visible par l'equipe). Le `list` rend aussi le statut, les etiquettes et les fiches HORS referentiel — ne jamais conclure « pas dans votre base » sans l'avoir appele. Trouver un identifiant : annuaire_entreprises. Pour les recherches sauvegardees : evenements_alertes. Les contacts et les communes ne s'ecrivent pas ici : annuaire_contacts et mairies_deliberations.

| | |
|---|---|
| Effets | lecture et écriture dans l'espace du compte |
| Portée OAuth | `mcp:write` |
| Offre requise | aucune — ouvert à tous les comptes |
| Données lues | l'espace du compte authentifié (ses alertes, ses dossiers, sa base) |
| Distribution | MCP historique |

Cet outil n'a pas d'équivalent REST : il s'appelle par le connecteur MCP.

## Paramètres

| Paramètre | Type | Requis | Bornes | Description |
|---|---|---|---|---|
| `acheteur_id` | texte | — | — | UUID de l'acheteur public (type=acheteur). |
| `action` | `list` · `add` · `remove` · `qualifier` · `etiqueter` · `noter` | oui | — | list/add/remove gerent la PRESENCE dans la base ; qualifier/etiqueter/noter posent la couche de travail sur une fiche qui y est deja. |
| `cle` | texte | — | min. caractères 8, max. caractères 160 | Pour un projet, clé unique de l’intention : rejouer la même clé évite de doubler une note. |
| `entreprise_id` | texte | — | — | UUID entreprise (CORE). |
| `limit` | entier | — | min 1, max 100 | — |
| `nom` | texte | — | — | action=add, type=entreprise, SANS siren/siret : cree une fiche HORS REFERENTIEL pour un acteur absent de l'annuaire. Elle ne se mettra pas a jour toute seule — a n'utiliser que si la recherche par nom n'a rien rendu. |
| `note` | texte | — | — | action=noter : le texte, visible par toute l'equipe. |
| `page` | entier | — | min 1 | — |
| `projet_id` | texte | — | — | UUID du projet detecte (type=projet). Il se lit dans un action:"list" type:"projet" ou sur l'ecran Projets ; projets_rechercher permet aussi de le rechercher. |
| `retirer` | booléen | — | — | action=etiqueter : true retire l'etiquette au lieu de la poser. |
| `scope` | `me` · `team` | — | — | Portee du list : me (defaut) ou team. SANS EFFET — une fiche appartient a l'organisation, la reponse le dit (scope_applique). |
| `siren` | texte | — | — | SIREN 9 chiffres (type=entreprise). |
| `siret` | texte | — | — | SIRET 14 chiffres (type=entreprise ou acheteur). |
| `statut` | `prospect` · `client` · `a_qualifier` · `concurrent` · `null` | — | — | action=qualifier, type=entreprise. `null` RETIRE la qualification (geste reel, pas une absence). |
| `tag` | texte | — | — | action=etiqueter : le libelle de l'etiquette. La casse et les accents sont ignores (« Maconnerie » = « MAÇONNERIE »). |
| `type` | `entreprise` · `acheteur` · `projet` | oui | — | Type d'entite suivie. Les CONTACTS ne s'ecrivent pas ici (opt-out et coordonnees encadres) : les lire avec annuaire_contacts. |
| `ville` | texte | — | — | Ville de la fiche hors referentiel (avec `nom`). |

## Exemple d'appel

_squelette synthétique : les repères `<…>` se remplacent._

```json
{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "action": "list",
      "type": "entreprise"
    },
    "name": "base_suivis"
  }
}
```

En HTTP, c'est ce corps que l'on poste :

```bash
curl -sS https://prescriptio.fr/api/mcp \
  -H 'Authorization: Bearer <jeton>' \
  -H 'Content-Type: application/json' \
  -d '{"id":1,"jsonrpc":"2.0","method":"tools/call","params":{"arguments":{"action":"list","type":"entreprise"},"name":"base_suivis"}}'
```

## Forme de la réponse

Le résultat est enveloppé par le protocole : un bloc `content[0].text` qui porte le JSON sérialisé, et `structuredContent` qui porte le même objet. Le squelette ci-dessous donne les **types**, jamais des valeurs réelles.

```json
{
  "action": "<texte>",
  "download_url": "<texte>",
  "fields": {},
  "files": [
    {}
  ],
  "ok": false,
  "page": 0,
  "pages_total": 0,
  "quota": {},
  "texte": "<texte>"
}
```

Un champ absent ou `null` n'est ni un zéro ni une estimation : la source ne l'a pas renseigné. Les propriétés additionnelles restent autorisées ; ce squelette n'invente pas les champs manquants.

## Erreurs

Le connecteur MCP renvoie une erreur JSON-RPC pour ce qui empêche l'appel, et une erreur *métier* (`isError`) lisible par le modèle pour ce que l'appel n'a pas pu faire.

| Code JSON-RPC | Quand | Que faire |
|---|---|---|
| `-32601` | Outil inconnu | Appeler `tools/list` ; ne pas deviner un nom |
| `-32602` | Argument absent ou hors schéma | Corriger l'argument nommé dans le message |
| `-32003` | Portée OAuth absente de l'autorisation | Reconnecter en acceptant `mcp:read` ou `mcp:write` |
| `-32004` | Quota dépassé | Attendre le délai indiqué ; ne jamais boucler |
| `-32603` | Dépendance indisponible | Réessayer plus tard ; ne pas rejouer une écriture sans vérifier |

Sur les routes REST `/api/mcp/v1/*`, les mêmes situations sont des codes HTTP : `400 invalid_arguments` / `invalid_cursor`, `401 unauthenticated`, `403 insufficient_scope` / `access_denied` / `user_required` / `organization_required` / `role_denied`, `404 not_found`, `409 conflict`, `429 quota_exceeded` (avec `Retry-After` quand il est connu), `503 unavailable`, `504 timeout`. Le corps porte `error.code`, `error.message`, `error.retry_after_seconds` et `api_contract_version`.

⚠ Un message d'erreur n'est jamais une donnée : ne pas le recopier comme un fait, et ne pas inventer un identifiant ou une URL qu'il ne contient pas.

## Quotas

Un appel compte pour **une unité** dans les deux compteurs d'appels, partagés entre le connecteur MCP et les routes REST :

| Compteur | Compte gratuit | Abonné | Accès interne |
|---|---|---|---|
| Appels / 24 h glissantes | 100 | 5000 | illimité |
| Appels / 60 s (anti-rafale) | 5 | 30 | illimité |
| Dossiers distincts / jour civil (Paris) | 5 | 500 | illimité |

Cet outil ne consomme aucune unité de dossier : chercher est gratuit, c'est la lecture d'un dossier (`marches_dce`, `mairies_deliberations` et leurs téléchargements) qui est décomptée.

**Aucun outil n'est réservé à une offre** (décision du 2026-09-17) : un compte gratuit voit et appelle le catalogue entier, ce sont ces plafonds qui bornent son usage.

## Voir aussi

[Référence technique](/docs/reference/concepts.md) · [Tous les outils](/docs/api/index.md) · [OpenAPI](/openapi.json) · [Texte pour agents](/llms-full.txt)
