203 lines
8.6 KiB
Markdown
203 lines
8.6 KiB
Markdown
# crowdlending-mcp-server
|
|
|
|
Serveur MCP (HTTP, Streamable HTTP transport) pour le portefeuille de
|
|
crowdlending. Il expose en lecture seule les données d'un investisseur
|
|
(investissements, remboursements, dépôts/retraits, dashboard) à un client
|
|
MCP — Claude Desktop, Claude Code, ou tout autre client compatible — en
|
|
s'appuyant sur l'API publique `/api/v1` du backend.
|
|
|
|
Il ne fait aucune écriture : toutes les modifications restent à faire dans
|
|
l'app web.
|
|
|
|
**Un seul serveur, un seul fichier (`server.js`)**, utilisé aussi bien en
|
|
développement local (`npm run dev`, comme le backend et le frontend) qu'en
|
|
production (service Docker `crowdlending-mcp`, derrière Traefik sur
|
|
`mcp.crowdlending.croguennec.net`). Pas de distinction de code entre les
|
|
deux — seule la configuration change (quelle API cibler, quels outils
|
|
activer).
|
|
|
|
## Prérequis
|
|
|
|
- Node.js ≥ 18 (fetch natif requis)
|
|
- Une clé API générée dans l'app : **Mon compte → Clés API → Nouvelle clé**
|
|
- Le backend accessible (en local `http://localhost:4000`, ou l'URL de votre
|
|
instance en production)
|
|
|
|
## Développement local
|
|
|
|
Comme pour `backend/` et `frontend/` :
|
|
|
|
```
|
|
cd mcp-server
|
|
npm install
|
|
npm run dev
|
|
```
|
|
|
|
`npm run dev` (comme `backend`) relance automatiquement le serveur à chaque
|
|
modification de fichier (`node --watch`). Par défaut, il écoute sur
|
|
`http://localhost:4100` et cible l'API locale (`http://localhost:4000/api/v1`).
|
|
|
|
Connectez ensuite Claude Desktop : Réglages → Développeur → Serveurs MCP
|
|
locaux → **Modifier la config**, puis ajoutez dans `mcpServers` :
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"crowdlending-dev": {
|
|
"url": "http://localhost:4100/mcp",
|
|
"headers": {
|
|
"X-API-Key": "clk_live_..."
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Redémarrez Claude Desktop. Les outils `crowdlending_*` doivent apparaître
|
|
(voir la liste plus bas — `crowdlending_fetch_url` en plus si activé, voir
|
|
Configuration).
|
|
|
|
## Configuration
|
|
|
|
Variables d'environnement, toutes optionnelles sauf pour un déploiement
|
|
distant réel (en local, les valeurs par défaut conviennent) :
|
|
|
|
| Variable | Défaut | Description |
|
|
|---|---|---|
|
|
| `PORT` | `4100` | Port d'écoute HTTP |
|
|
| `CROWDLENDING_API_URL` | `http://localhost:4000/api/v1` | API v1 ciblée |
|
|
| `MCP_LABEL` | — | Étiquette d'environnement (`dev`, `prod`...) — voir plus bas |
|
|
| `MCP_ENABLE_FETCH_URL` | `false` | Active l'outil `crowdlending_fetch_url` (voir plus bas) |
|
|
| `MCP_ALLOWED_HOSTS` | `mcp.crowdlending.croguennec.net,localhost` | En-têtes `Host` acceptés (protection anti DNS-rebinding) |
|
|
|
|
Aucune clé API fixe n'est configurée côté serveur, contrairement à une
|
|
ancienne version qui utilisait le transport stdio : chaque session MCP lit
|
|
sa propre clé dans l'en-tête `X-API-Key` de la requête qui l'initialise (le
|
|
bloc `headers` de la config Claude Desktop ci-dessus). Un même process peut
|
|
donc servir plusieurs utilisateurs/sessions en parallèle sans jamais mélanger
|
|
leurs données — voir le déploiement distant plus bas.
|
|
|
|
## Faire tourner dev et prod en même temps
|
|
|
|
Claude Desktop peut se connecter à plusieurs serveurs MCP simultanément : il
|
|
suffit de déclarer deux entrées dans `mcpServers`, une par URL. Chaque outil
|
|
est automatiquement rattaché à son serveur d'origine — pas de collision
|
|
possible, même si les noms d'outils sont identiques des deux côtés.
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"crowdlending-dev": {
|
|
"url": "http://localhost:4100/mcp",
|
|
"headers": { "X-API-Key": "clk_live_..." }
|
|
},
|
|
"crowdlending-prod": {
|
|
"url": "https://mcp.crowdlending.croguennec.net/mcp",
|
|
"headers": { "X-API-Key": "clk_live_..." }
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Utilisez deux clés API différentes (une par instance) : ça permet de
|
|
révoquer l'une sans affecter l'autre. Réglez `MCP_LABEL=dev` (côté serveur
|
|
local, dans votre `.env` ou variable d'environnement au lancement) pour que
|
|
le titre de chaque outil affiche `[DEV]` et lève toute ambiguïté — le
|
|
serveur distant est déjà configuré avec `MCP_LABEL` correspondant en
|
|
production.
|
|
|
|
## Déploiement en production (Docker)
|
|
|
|
Le service `crowdlending-mcp` du `docker-compose.yml` à la racine construit
|
|
et lance ce même `server.js`, exposé via Traefik sur
|
|
`mcp.crowdlending.croguennec.net` (certificat TLS automatique). Contrairement
|
|
au reste de l'app, ce service n'a **pas** le middleware `ipwhitelist-all` :
|
|
il est volontairement accessible depuis internet, pour des utilisateurs
|
|
distants qui ne peuvent pas faire tourner le serveur en local — la clé API
|
|
est donc la seule barrière d'accès. Traitez-la comme un mot de passe, et
|
|
révoquez-la immédiatement en cas de doute (Mon compte → Clés API).
|
|
|
|
Un enregistrement DNS pour ce sous-domaine, pointant vers la même IP que
|
|
`crowdlending.croguennec.net`, est nécessaire avant le premier déploiement.
|
|
|
|
`MCP_ENABLE_FETCH_URL` reste à `false` en production (voir docker-compose.yml)
|
|
: cet outil lit une URL arbitraire fournie par l'appelant, acceptable pour
|
|
un usage perso où vous seul détenez la clé, mais risqué (SSRF) face à des
|
|
utilisateurs distants non maîtrisés.
|
|
|
|
Autres protections : limite de 60 requêtes/minute par IP (au-delà, `429`),
|
|
et fermeture automatique des sessions inactives depuis plus de 30 minutes
|
|
(mémoire uniquement, aucune persistance).
|
|
|
|
## Tester sans Claude Desktop
|
|
|
|
Le [MCP Inspector](https://github.com/modelcontextprotocol/inspector) permet
|
|
de lister et appeler les outils depuis une interface web :
|
|
|
|
```
|
|
npm run inspect
|
|
```
|
|
|
|
Dans l'interface, choisissez le transport **Streamable HTTP**, entrez
|
|
l'URL (`http://localhost:4100/mcp` en dev) et ajoutez l'en-tête
|
|
`X-API-Key` avec votre clé.
|
|
|
|
## Outils exposés
|
|
|
|
Tous en lecture seule (`readOnlyHint: true`) :
|
|
|
|
| Outil | Description |
|
|
|---|---|
|
|
| `crowdlending_get_investisseur` | Profil de l'investisseur lié à la clé |
|
|
| `crowdlending_get_dashboard` | Synthèse KPI : capital investi, capital en risque, intérêts perçus (filtrable par année), cash |
|
|
| `crowdlending_list_investissements` | Liste des investissements, filtrable par statut |
|
|
| `crowdlending_get_investissement` | Détail d'un investissement + ses remboursements |
|
|
| `crowdlending_list_remboursements` | Historique des remboursements, filtrable par période |
|
|
| `crowdlending_list_depots_retraits` | Historique des mouvements de cash |
|
|
| `crowdlending_fetch_url` | *(actif seulement si `MCP_ENABLE_FETCH_URL=true`)* Lit une page web (annonce de projet) et en extrait le texte propre — voir ci-dessous |
|
|
|
|
## Lire une annonce de projet (`crowdlending_fetch_url`)
|
|
|
|
Désactivé par défaut — à activer avec `MCP_ENABLE_FETCH_URL=true`,
|
|
typiquement en développement local uniquement (voir Configuration et
|
|
Sécurité plus haut).
|
|
|
|
Cet outil récupère une page web et en extrait le contenu lisible (titre +
|
|
texte principal) via [Readability](https://github.com/mozilla/readability),
|
|
la librairie du mode lecture de Firefox — menus, pubs, scripts et bandeaux
|
|
cookies sont éliminés automatiquement.
|
|
|
|
Il ne fait **aucune extraction métier** côté serveur (pas de tentative de
|
|
deviner taux/montant/durée par regex) : c'est l'agent qui lit le texte
|
|
retourné et en extrait les informations pertinentes dans la conversation,
|
|
pour vous les proposer avant toute saisie. Cohérent avec le reste du
|
|
serveur : lecture seule, aucune création automatique d'investissement (l'API
|
|
v1 n'a pas de capacité d'écriture).
|
|
|
|
Exemple d'usage : *« Regarde cette page et propose-moi les infos pour créer
|
|
l'investissement : https://plateforme.fr/projets/xxx »*.
|
|
|
|
Garde-fous :
|
|
- http/https uniquement, pages HTML uniquement.
|
|
- Hôtes locaux/privés bloqués (`localhost`, `127.0.0.1`, plages `10.x`/`172.16-31.x`/`192.168.x`...) —
|
|
l'outil ne peut pas cibler votre réseau local, y compris votre propre backend.
|
|
- Texte tronqué à 8000 caractères sur les pages très longues (le champ
|
|
`truncated` de la réponse l'indique).
|
|
|
|
## Dépannage
|
|
|
|
- **`En-tête X-API-Key manquant`** — vérifiez la section `headers` de votre
|
|
config Claude Desktop.
|
|
- **`Clé API invalide ou révoquée`** — régénérez une clé dans Mon compte →
|
|
Clés API et mettez à jour la config.
|
|
- **`Impossible de joindre l'API`** — le backend n'est pas démarré, ou
|
|
`CROWDLENDING_API_URL` pointe au mauvais endroit (vérifiez le port et le
|
|
suffixe `/api/v1`).
|
|
- **`Invalid Host` (403)** — l'en-tête `Host` de la requête ne correspond à
|
|
aucune valeur de `MCP_ALLOWED_HOSTS`. En local, vérifiez que vous appelez
|
|
bien `localhost:4100` (pas `127.0.0.1:4100`, absent de la liste par
|
|
défaut — ajoutez-le à `MCP_ALLOWED_HOSTS` si besoin).
|
|
- **Session `404` après une longue pause** — la session a expiré après 30
|
|
minutes d'inactivité, votre client MCP doit s'y reconnecter (généralement
|
|
automatique).
|