Update MCP server

This commit is contained in:
2026-07-15 22:59:44 +02:00
parent 5a0a1c03ac
commit 56dd1f89bd
9 changed files with 341 additions and 491 deletions
+111 -167
View File
@@ -1,28 +1,20 @@
# crowdlending-mcp-server
Serveur MCP 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.
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.
Deux modes, deux fichiers :
- **Local (`index.js`, stdio)** — lancé comme process enfant par Claude
Desktop sur votre propre machine. Nécessite Node.js et ce dépôt cloné en
local. Inclut l'outil `crowdlending_fetch_url` (lecture de page web).
- **Distant (`http-server.js`, HTTP)** — un service déployé une fois (par
l'administrateur de l'instance) sur `mcp.crowdlending.croguennec.net`,
accessible à n'importe quel utilisateur distant sans rien installer :
juste une URL + sa clé API personnelle à coller dans son client MCP.
N'inclut PAS `crowdlending_fetch_url` (voir plus bas).
Les deux partagent le même code pour les 6 outils de lecture de données
(`tools.js`) — leur comportement ne peut donc pas diverger entre les deux
modes.
**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
@@ -31,130 +23,28 @@ modes.
- Le backend accessible (en local `http://localhost:4000`, ou l'URL de votre
instance en production)
## Installation
## Développement local
Comme pour `backend/` et `frontend/` :
```
cd mcp-server
npm install
npm run dev
```
## Configuration
`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`).
Trois variables d'environnement :
| Variable | Obligatoire | Défaut | Exemple |
|---|---|---|---|
| `CROWDLENDING_API_KEY` | oui | — | `clk_live_...` |
| `CROWDLENDING_API_URL` | non | `http://localhost:4000/api/v1` | `https://mon-domaine.fr/api/v1` |
| `CROWDLENDING_LABEL` | non | — | `dev`, `prod` |
`CROWDLENDING_LABEL` sert uniquement à distinguer plusieurs instances
connectées en même temps (voir [Faire tourner dev et prod en même
temps](#faire-tourner-dev-et-prod-en-même-temps)) : il apparaît dans le nom
du serveur, dans le titre de chaque outil (`[DEV]` / `[PROD]`) et dans la
description (avec l'URL API ciblée), pour que l'agent — et vous — sachiez
toujours quel environnement est interrogé.
## Utiliser avec Claude Desktop
Localisez le fichier de config Claude Desktop — le chemin diffère selon la
provenance de l'installation Windows :
- **Installeur classique** (téléchargé depuis claude.ai) :
`%APPDATA%\Claude\claude_desktop_config.json`
- **Microsoft Store** : Windows redirige `%APPDATA%` vers un dossier virtualisé
propre à l'app —
`%LOCALAPPDATA%\Packages\Claude_<id>\LocalCache\Roaming\Claude\claude_desktop_config.json`
(le `<id>` est un identifiant généré, propre à votre installation).
Le plus fiable dans les deux cas : Réglages → Développeur → Serveurs MCP
locaux → **Modifier la config**, qui ouvre directement le bon fichier quelle
que soit la provenance de l'installation.
Ajoutez une entrée dans `mcpServers` :
```json
{
"mcpServers": {
"crowdlending": {
"command": "node",
"args": ["C:\\dev\\crowdlending-app\\mcp-server\\index.js"],
"env": {
"CROWDLENDING_API_KEY": "clk_live_...",
"CROWDLENDING_API_URL": "http://localhost:4000/api/v1"
}
}
}
}
```
Redémarrez Claude Desktop. L'icône 🔌 (ou le menu des outils MCP) doit
afficher les 7 outils `crowdlending_*` ci-dessous.
Pour pointer vers votre instance de production plutôt que le backend local,
changez uniquement `CROWDLENDING_API_URL` (et utilisez une clé API générée
sur cette instance).
## 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 avec des clés distinctes dans `mcpServers`.
Chaque outil est alors automatiquement rattaché à son serveur d'origine —
pas de collision technique possible entre les deux, même si les noms
d'outils (`crowdlending_get_dashboard`, etc.) sont identiques des deux côtés.
Connectez ensuite Claude Desktop : Réglages → Développeur → Serveurs MCP
locaux → **Modifier la config**, puis ajoutez dans `mcpServers` :
```json
{
"mcpServers": {
"crowdlending-dev": {
"command": "node",
"args": ["C:\\dev\\crowdlending-app\\mcp-server\\index.js"],
"env": {
"CROWDLENDING_API_KEY": "clk_live_...",
"CROWDLENDING_API_URL": "http://localhost:4000/api/v1",
"CROWDLENDING_LABEL": "dev"
}
},
"crowdlending-prod": {
"command": "node",
"args": ["C:\\dev\\crowdlending-app\\mcp-server\\index.js"],
"env": {
"CROWDLENDING_API_KEY": "clk_live_...",
"CROWDLENDING_API_URL": "https://mon-domaine.fr/api/v1",
"CROWDLENDING_LABEL": "prod"
}
}
}
}
```
Utilisez deux clés API différentes (une par instance, générées séparément
sur chaque backend) : ça permet de révoquer l'une sans affecter l'autre, et
c'est cohérent avec le principe d'une clé par usage.
Avec `CROWDLENDING_LABEL` renseigné, chaque outil affiche son environnement
dans son titre (ex. « Synthèse du portefeuille [PROD] ») et sa description
se termine par la source exacte interrogée — de quoi lever toute ambiguïté
si vous demandez « mon encours en prod » vs « mon encours en dev ».
## Serveur distant — pour les utilisateurs sans installation locale
Si vous n'êtes pas sur la machine qui héberge ce dépôt (pas de Node.js, pas
envie de cloner le repo), vous pouvez vous connecter directement au serveur
MCP distant déployé sur `https://mcp.crowdlending.croguennec.net` — aucune
installation nécessaire, juste votre clé API personnelle.
**1. Créer votre clé API** — dans l'app, Mon compte → Clés API → Nouvelle
clé (elle ne sera affichée qu'une seule fois, copiez-la).
**2. Ajouter le serveur dans Claude Desktop** — Réglages → Développeur →
Serveurs MCP locaux → Modifier la config, puis ajoutez :
```json
{
"mcpServers": {
"crowdlending-distant": {
"url": "https://mcp.crowdlending.croguennec.net/mcp",
"url": "http://localhost:4100/mcp",
"headers": {
"X-API-Key": "clk_live_..."
}
@@ -163,52 +53,95 @@ Serveurs MCP locaux → Modifier la config, puis ajoutez :
}
```
**3. Redémarrez Claude Desktop.** Les 6 outils `crowdlending_*` doivent
apparaître (sans `crowdlending_fetch_url`, réservé au serveur local).
Redémarrez Claude Desktop. Les outils `crowdlending_*` doivent apparaître
(voir la liste plus bas — `crowdlending_fetch_url` en plus si activé, voir
Configuration).
### Différences avec le serveur local
## Configuration
- **Pas de `crowdlending_fetch_url`** : lire une page web arbitraire pour un
utilisateur tiers non maîtrisé augmenterait le risque SSRF sans bénéfice
réel pour ce cas d'usage. Cet outil reste réservé au serveur local.
- **Authentification par requête, pas par process** : le serveur local a une
clé API fixée une fois pour toutes via une variable d'environnement — un
process = un utilisateur. Le serveur distant sert plusieurs utilisateurs en
parallèle : chaque session est créée à partir de la clé API envoyée dans
l'en-tête `X-API-Key` de la requête qui l'initialise, puis liée à cette
session uniquement. Deux utilisateurs ne partagent jamais de données.
- **Exposé publiquement, sans la liste blanche d'IP** qui protège le reste de
l'app (`ipwhitelist-all`) : la clé API est la seule barrière d'accès.
Traitez-la comme un mot de passe — ne la partagez pas, révoquez-la
immédiatement en cas de doute (Mon compte → Clés API).
- **Limite de débit** : 60 requêtes/minute par adresse IP, au-delà l'API
répond `429`.
- **Sessions** : une session inactive plus de 30 minutes est fermée côté
serveur (mémoire uniquement, aucune persistance) ; votre client MCP en
recréera une automatiquement à la prochaine requête.
Variables d'environnement, toutes optionnelles sauf pour un déploiement
distant réel (en local, les valeurs par défaut conviennent) :
### Déploiement (administrateur de l'instance)
| 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) |
Le service `crowdlending-mcp` du `docker-compose.yml` construit et lance
`http-server.js`, exposé via Traefik sur `mcp.crowdlending.croguennec.net`
(certificat TLS automatique, même resolver que le reste de l'app). Un
enregistrement DNS pour ce sous-domaine, pointant vers la même IP que
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.
Variables d'environnement du service : `CROWDLENDING_API_URL` (URL interne
du backend sur le réseau Docker, déjà configurée) et `MCP_ALLOWED_HOSTS`
(validation de l'en-tête `Host`, protection anti DNS-rebinding — doit
correspondre exactement au(x) nom(s) de domaine exposé(s)).
`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, sans configurer de
client :
de lister et appeler les outils depuis une interface web :
```
CROWDLENDING_API_KEY=clk_live_... npm run inspect
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`) :
@@ -221,10 +154,14 @@ Tous en lecture seule (`readOnlyHint: true`) :
| `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` | *(serveur local uniquement)* Lit une page web (annonce de projet) et en extrait le texte propre — voir ci-dessous |
| `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
@@ -249,10 +186,17 @@ Garde-fous :
## Dépannage
- **`ERREUR : CROWDLENDING_API_KEY est requise`** — la variable d'env n'est
pas transmise. Vérifiez la section `env` de votre config MCP.
- **`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).