Fix
This commit is contained in:
@@ -67,6 +67,7 @@ services:
|
|||||||
PORT: 4100
|
PORT: 4100
|
||||||
CROWDLENDING_API_URL: http://crowdlending-backend:4000/api/v1
|
CROWDLENDING_API_URL: http://crowdlending-backend:4000/api/v1
|
||||||
MCP_ALLOWED_HOSTS: mcp.crowdlending.croguennec.net,localhost
|
MCP_ALLOWED_HOSTS: mcp.crowdlending.croguennec.net,localhost
|
||||||
|
MCP_LABEL: prod
|
||||||
# Explicitement désactivé : ce serveur sert des utilisateurs distants
|
# Explicitement désactivé : ce serveur sert des utilisateurs distants
|
||||||
# non maîtrisés, l'outil de lecture d'URL arbitraire (SSRF) reste
|
# non maîtrisés, l'outil de lecture d'URL arbitraire (SSRF) reste
|
||||||
# réservé au développement local. Ne pas passer à true ici.
|
# réservé au développement local. Ne pas passer à true ici.
|
||||||
|
|||||||
@@ -1091,27 +1091,30 @@ function ApiKeysSection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ── Serveur MCP ──────────────────────────────────────────────
|
/* ── Serveur MCP ──────────────────────────────────────────────
|
||||||
Guide pas-à-pas pour connecter Claude Desktop au serveur MCP local
|
Guide pas-à-pas pour connecter Claude Desktop au serveur MCP
|
||||||
(mcp-server/ à la racine du projet). Le JSON de config est généré
|
(mcp-server/ à la racine du projet, un seul modèle url+headers en HTTP,
|
||||||
côté client à partir des champs ci-dessous ; la clé API saisie ici
|
que ce soit en développement local ou déployé à distance en prod — voir
|
||||||
reste uniquement en mémoire du navigateur, elle n'est jamais envoyée
|
mcp-server/README.md). Le JSON de config est généré côté client à partir
|
||||||
au backend — seulement utilisée pour composer l'aperçu à copier. ── */
|
des champs ci-dessous ; la clé API saisie ici reste uniquement en mémoire
|
||||||
|
du navigateur, elle n'est jamais envoyée au backend — seulement utilisée
|
||||||
|
pour composer l'aperçu à copier. ── */
|
||||||
|
|
||||||
/** Devine une URL d'API raisonnable selon l'environnement courant :
|
/** Devine une URL de serveur MCP raisonnable selon l'environnement courant :
|
||||||
* en dev (Vite sur :5173), le process Node du serveur MCP ne passe pas
|
* en dev (Vite sur :5173 ou localhost), le serveur MCP tourne en local sur
|
||||||
* par le proxy Vite, il faut donc viser directement le port du backend (4000).
|
* son port par défaut (npm run dev, :4100). En prod, il s'agit du
|
||||||
* En prod (nginx sert front + /api sur la même origine), l'origine courante convient. */
|
* sous-domaine dédié mcp.<domaine de l'app>, déjà déployé en continu. */
|
||||||
function guessMcpApiUrl() {
|
function guessMcpUrl() {
|
||||||
if (typeof window === 'undefined') return 'http://localhost:4000/api/v1';
|
if (typeof window === 'undefined') return 'http://localhost:4100/mcp';
|
||||||
const { hostname, port, origin } = window.location;
|
const { hostname, port } = window.location;
|
||||||
if (port === '5173') return `http://${hostname}:4000/api/v1`;
|
if (port === '5173' || hostname === 'localhost' || hostname === '127.0.0.1') {
|
||||||
return `${origin}/api/v1`;
|
return 'http://localhost:4100/mcp';
|
||||||
|
}
|
||||||
|
return `https://mcp.${hostname}/mcp`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Détecte automatiquement l'environnement ('dev' ou 'prod') à partir de
|
/** Détecte automatiquement l'environnement ('dev' ou 'prod') à partir de
|
||||||
* l'URL de l'API : localhost/IP locale ou nom d'hôte contenant "dev" →
|
* l'URL du serveur MCP : localhost/IP locale → dev, tout le reste → prod.
|
||||||
* dev, tout le reste → prod. Best-effort — reste modifiable manuellement
|
* Best-effort — reste modifiable manuellement pour les cas particuliers. */
|
||||||
* pour les cas particuliers (domaine de test qui ne contient pas "dev"...). */
|
|
||||||
function detectLabelFromUrl(url) {
|
function detectLabelFromUrl(url) {
|
||||||
if (!url) return 'prod';
|
if (!url) return 'prod';
|
||||||
let hostname;
|
let hostname;
|
||||||
@@ -1146,27 +1149,28 @@ function CopyBlock({ text }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function McpServerSection({ goToApiKeys }) {
|
function McpServerSection({ goToApiKeys }) {
|
||||||
const [mcpPath, setMcpPath] = useState('C:\\dev\\crowdlending-app\\mcp-server\\index.js');
|
const [mcpUrl, setMcpUrl] = useState(guessMcpUrl());
|
||||||
const [apiUrl, setApiUrl] = useState(guessMcpApiUrl());
|
|
||||||
const [apiKey, setApiKey] = useState('');
|
const [apiKey, setApiKey] = useState('');
|
||||||
const [manualLabel, setManualLabel] = useState(null); // null = auto-détecté depuis apiUrl, sinon override manuel
|
const [manualLabel, setManualLabel] = useState(null); // null = auto-détecté depuis mcpUrl, sinon override manuel
|
||||||
|
|
||||||
const detectedLabel = detectLabelFromUrl(apiUrl);
|
const detectedLabel = detectLabelFromUrl(mcpUrl);
|
||||||
const label = manualLabel ?? detectedLabel;
|
const label = manualLabel ?? detectedLabel;
|
||||||
|
const isLocal = label === 'dev';
|
||||||
|
|
||||||
const serverKey = `crowdlending-${label}`;
|
const serverKey = `crowdlending-${label}`;
|
||||||
const env = {
|
// claude_desktop_config.json n'a pas de champ url/headers natif : on passe
|
||||||
CROWDLENDING_API_KEY: apiKey || '<VOTRE_CLE_API>',
|
// par mcp-remote (https://github.com/geelen/mcp-remote), un pont stdio↔HTTP
|
||||||
CROWDLENDING_API_URL: apiUrl,
|
// que Claude Desktop lance comme n'importe quel serveur "command". La clé
|
||||||
CROWDLENDING_LABEL: label,
|
// API passe en variable d'environnement plutôt que directement dans args
|
||||||
};
|
// (bug connu de Claude Desktop Windows qui tronque les valeurs à espaces).
|
||||||
|
const envVarName = `${label.toUpperCase()}_API_KEY`;
|
||||||
|
|
||||||
const configJson = JSON.stringify({
|
const configJson = JSON.stringify({
|
||||||
mcpServers: {
|
mcpServers: {
|
||||||
[serverKey]: {
|
[serverKey]: {
|
||||||
command: 'node',
|
command: 'npx',
|
||||||
args: [mcpPath],
|
args: ['-y', 'mcp-remote', mcpUrl, '--header', `X-API-Key:\${${envVarName}}`],
|
||||||
env,
|
env: { [envVarName]: apiKey || '<VOTRE_CLE_API>' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, null, 2);
|
}, null, 2);
|
||||||
@@ -1176,8 +1180,8 @@ function McpServerSection({ goToApiKeys }) {
|
|||||||
<h3 style={{ margin: '0 0 4px' }}>Serveur MCP</h3>
|
<h3 style={{ margin: '0 0 4px' }}>Serveur MCP</h3>
|
||||||
<p className="text-muted" style={{ margin: '0 0 20px', fontSize: 'var(--fs-sm)' }}>
|
<p className="text-muted" style={{ margin: '0 0 20px', fontSize: 'var(--fs-sm)' }}>
|
||||||
Permet à Claude Desktop (ou tout client MCP) de consulter votre portefeuille en lecture seule.
|
Permet à Claude Desktop (ou tout client MCP) de consulter votre portefeuille en lecture seule.
|
||||||
Le serveur (dossier <code>mcp-server/</code> du projet) doit être installé sur cette machine
|
Un seul modèle de connexion, en développement local comme en production : une URL de serveur MCP
|
||||||
(<code>npm install</code>) — voir <code>mcp-server/README.md</code> pour le détail.
|
et votre clé API personnelle — voir <code>mcp-server/README.md</code> pour le détail.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h4 style={{ margin: '0 0 6px', fontSize: 'var(--fs-sm)' }}>1. Créer une clé API dédiée</h4>
|
<h4 style={{ margin: '0 0 6px', fontSize: 'var(--fs-sm)' }}>1. Créer une clé API dédiée</h4>
|
||||||
@@ -1194,12 +1198,8 @@ function McpServerSection({ goToApiKeys }) {
|
|||||||
<h4 style={{ margin: '0 0 10px', fontSize: 'var(--fs-sm)' }}>2. Renseigner les paramètres</h4>
|
<h4 style={{ margin: '0 0 10px', fontSize: 'var(--fs-sm)' }}>2. Renseigner les paramètres</h4>
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 12, marginBottom: 20, maxWidth: 520 }}>
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 12, marginBottom: 20, maxWidth: 520 }}>
|
||||||
<div>
|
<div>
|
||||||
<label>Chemin vers mcp-server/index.js</label>
|
<label>URL du serveur MCP</label>
|
||||||
<input value={mcpPath} onChange={e => setMcpPath(e.target.value)} />
|
<input value={mcpUrl} onChange={e => setMcpUrl(e.target.value)} />
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label>URL de l'API</label>
|
|
||||||
<input value={apiUrl} onChange={e => setApiUrl(e.target.value)} />
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label>Clé API</label>
|
<label>Clé API</label>
|
||||||
@@ -1218,7 +1218,7 @@ function McpServerSection({ goToApiKeys }) {
|
|||||||
</span>
|
</span>
|
||||||
<span style={{ fontSize: 'var(--fs-sm)', color: 'var(--text-muted)' }}>
|
<span style={{ fontSize: 'var(--fs-sm)', color: 'var(--text-muted)' }}>
|
||||||
{manualLabel === null
|
{manualLabel === null
|
||||||
? <>déduit de l'URL de l'API ci-dessus (localhost / « dev » → dev, sinon prod)</>
|
? <>déduit de l'URL ci-dessus (localhost → dev, sinon prod)</>
|
||||||
: <>forcé manuellement</>}
|
: <>forcé manuellement</>}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -1236,12 +1236,26 @@ function McpServerSection({ goToApiKeys }) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{isLocal ? (
|
||||||
<p style={{ margin: '-8px 0 20px', fontSize: 'var(--fs-sm)', color: 'var(--text-muted)' }}>
|
<p style={{ margin: '-8px 0 20px', fontSize: 'var(--fs-sm)', color: 'var(--text-muted)' }}>
|
||||||
|
En développement, ce serveur doit tourner sur votre machine pour que l'URL ci-dessus réponde :
|
||||||
|
<code style={{ display: 'block', margin: '6px 0', padding: '6px 8px', borderRadius: 6, background: 'var(--surface-2, #f9fafb)' }}>
|
||||||
|
cd mcp-server && npm install && npm run dev
|
||||||
|
</code>
|
||||||
|
comme pour le backend et le frontend. Laissez ce terminal ouvert tant que vous utilisez Claude Desktop.
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
|
<p style={{ margin: '-8px 0 20px', fontSize: 'var(--fs-sm)', color: 'var(--text-muted)' }}>
|
||||||
|
En production, le serveur tourne déjà en continu (service <code>crowdlending-mcp</code>) — aucune
|
||||||
|
action nécessaire au-delà de renseigner l'URL et votre clé API.
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
<p style={{ margin: '0 0 20px', fontSize: 'var(--fs-sm)', color: 'var(--text-muted)' }}>
|
||||||
Claude Desktop peut se connecter à plusieurs serveurs MCP en même temps : pour avoir dev et
|
Claude Desktop peut se connecter à plusieurs serveurs MCP en même temps : pour avoir dev et
|
||||||
prod accessibles simultanément, répétez ces étapes une deuxième fois avec une URL d'API pointant
|
prod accessibles simultanément, répétez ces étapes une deuxième fois avec l'autre URL (et une clé
|
||||||
vers l'autre environnement (et une clé API distincte) — l'étiquette et la clé de config
|
API distincte) — la clé de config (<code>{serverKey}</code> ci-dessous) s'ajuste automatiquement,
|
||||||
(<code>{serverKey}</code> ci-dessous) s'ajustent automatiquement. Elle apparaît dans le titre et
|
Claude Desktop ne confondra jamais les deux portefeuilles.
|
||||||
la description de chaque outil, pour que l'agent ne confonde jamais les deux portefeuilles.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h4 style={{ margin: '0 0 6px', fontSize: 'var(--fs-sm)' }}>3. Copier la configuration</h4>
|
<h4 style={{ margin: '0 0 6px', fontSize: 'var(--fs-sm)' }}>3. Copier la configuration</h4>
|
||||||
@@ -1268,8 +1282,10 @@ function McpServerSection({ goToApiKeys }) {
|
|||||||
|
|
||||||
<h4 style={{ margin: '0 0 6px', fontSize: 'var(--fs-sm)' }}>5. Vérifier</h4>
|
<h4 style={{ margin: '0 0 6px', fontSize: 'var(--fs-sm)' }}>5. Vérifier</h4>
|
||||||
<p style={{ margin: 0, fontSize: 'var(--fs-sm)', color: 'var(--text-muted)' }}>
|
<p style={{ margin: 0, fontSize: 'var(--fs-sm)', color: 'var(--text-muted)' }}>
|
||||||
Dans la liste des outils MCP de Claude Desktop, les 7 outils <code>crowdlending_*</code> doivent
|
Dans la liste des outils MCP de Claude Desktop, les outils <code>crowdlending_*</code> doivent
|
||||||
apparaître. Testez avec une question du type « Quel est mon encours de crowdlending actuellement ? ».
|
apparaître (6 en production, 7 en développement local si <code>crowdlending_fetch_url</code> est
|
||||||
|
activé — voir <code>mcp-server/README.md</code>). Testez avec une question du type « Quel est mon
|
||||||
|
encours de crowdlending actuellement ? ».
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
+39
-11
@@ -44,15 +44,37 @@ locaux → **Modifier la config**, puis ajoutez dans `mcpServers` :
|
|||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"crowdlending-dev": {
|
"crowdlending-dev": {
|
||||||
"url": "http://localhost:4100/mcp",
|
"command": "npx",
|
||||||
"headers": {
|
"args": [
|
||||||
"X-API-Key": "clk_live_..."
|
"-y",
|
||||||
|
"mcp-remote",
|
||||||
|
"http://localhost:4100/mcp",
|
||||||
|
"--header",
|
||||||
|
"X-API-Key:${CROWDLENDING_API_KEY}"
|
||||||
|
],
|
||||||
|
"env": {
|
||||||
|
"CROWDLENDING_API_KEY": "clk_live_..."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Important :** `claude_desktop_config.json` n'accepte que des entrées
|
||||||
|
`command`/`args` — il n'existe pas de champ `url`/`headers` natif dans ce
|
||||||
|
fichier (contrairement à d'autres clients MCP). Pour un serveur HTTP comme
|
||||||
|
celui-ci, on passe donc par
|
||||||
|
[`mcp-remote`](https://github.com/geelen/mcp-remote), un petit pont
|
||||||
|
stdio↔HTTP officiel : Claude Desktop lance `npx mcp-remote` comme d'habitude,
|
||||||
|
qui se charge de parler HTTP à notre serveur en coulisses, en-tête
|
||||||
|
`X-API-Key` inclus. Aucune installation manuelle requise, `npx` le télécharge
|
||||||
|
à la volée.
|
||||||
|
|
||||||
|
Notez l'absence d'espace autour du `:` dans `--header` : Claude Desktop
|
||||||
|
(Windows) a un bug connu qui tronque les arguments contenant un espace — on
|
||||||
|
passe donc la valeur réelle (avec l'espace éventuel) via une variable
|
||||||
|
d'environnement dans `env` plutôt que directement dans `args`.
|
||||||
|
|
||||||
Redémarrez Claude Desktop. Les outils `crowdlending_*` doivent apparaître
|
Redémarrez Claude Desktop. Les outils `crowdlending_*` doivent apparaître
|
||||||
(voir la liste plus bas — `crowdlending_fetch_url` en plus si activé, voir
|
(voir la liste plus bas — `crowdlending_fetch_url` en plus si activé, voir
|
||||||
Configuration).
|
Configuration).
|
||||||
@@ -72,8 +94,8 @@ distant réel (en local, les valeurs par défaut conviennent) :
|
|||||||
|
|
||||||
Aucune clé API fixe n'est configurée côté serveur, contrairement à une
|
Aucune clé API fixe n'est configurée côté serveur, contrairement à une
|
||||||
ancienne version qui utilisait le transport stdio : chaque session MCP lit
|
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
|
sa propre clé dans l'en-tête `X-API-Key` de la requête qui l'initialise
|
||||||
bloc `headers` de la config Claude Desktop ci-dessus). Un même process peut
|
(transmis via `mcp-remote --header`, voir ci-dessus). Un même process peut
|
||||||
donc servir plusieurs utilisateurs/sessions en parallèle sans jamais mélanger
|
donc servir plusieurs utilisateurs/sessions en parallèle sans jamais mélanger
|
||||||
leurs données — voir le déploiement distant plus bas.
|
leurs données — voir le déploiement distant plus bas.
|
||||||
|
|
||||||
@@ -88,12 +110,14 @@ possible, même si les noms d'outils sont identiques des deux côtés.
|
|||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"crowdlending-dev": {
|
"crowdlending-dev": {
|
||||||
"url": "http://localhost:4100/mcp",
|
"command": "npx",
|
||||||
"headers": { "X-API-Key": "clk_live_..." }
|
"args": ["-y", "mcp-remote", "http://localhost:4100/mcp", "--header", "X-API-Key:${DEV_API_KEY}"],
|
||||||
|
"env": { "DEV_API_KEY": "clk_live_..." }
|
||||||
},
|
},
|
||||||
"crowdlending-prod": {
|
"crowdlending-prod": {
|
||||||
"url": "https://mcp.crowdlending.croguennec.net/mcp",
|
"command": "npx",
|
||||||
"headers": { "X-API-Key": "clk_live_..." }
|
"args": ["-y", "mcp-remote", "https://mcp.crowdlending.croguennec.net/mcp", "--header", "X-API-Key:${PROD_API_KEY}"],
|
||||||
|
"env": { "PROD_API_KEY": "clk_live_..." }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,8 +210,12 @@ Garde-fous :
|
|||||||
|
|
||||||
## Dépannage
|
## Dépannage
|
||||||
|
|
||||||
- **`En-tête X-API-Key manquant`** — vérifiez la section `headers` de votre
|
- **`En-tête X-API-Key manquant`** — vérifiez l'argument `--header` et la
|
||||||
config Claude Desktop.
|
variable d'environnement correspondante dans votre config Claude Desktop.
|
||||||
|
- **« Certains serveurs MCP n'ont pas pu être chargés » / entrée ignorée** —
|
||||||
|
votre config utilise un bloc `url`/`headers` directement, non supporté par
|
||||||
|
`claude_desktop_config.json` (voir Développement local plus haut) : il faut
|
||||||
|
passer par `command: "npx"` + `mcp-remote`.
|
||||||
- **`Clé API invalide ou révoquée`** — régénérez une clé dans Mon compte →
|
- **`Clé API invalide ou révoquée`** — régénérez une clé dans Mon compte →
|
||||||
Clés API et mettez à jour la config.
|
Clés API et mettez à jour la config.
|
||||||
- **`Impossible de joindre l'API`** — le backend n'est pas démarré, ou
|
- **`Impossible de joindre l'API`** — le backend n'est pas démarré, ou
|
||||||
|
|||||||
Reference in New Issue
Block a user