MAj MCP Serveur
This commit is contained in:
+42
-1
@@ -41,6 +41,7 @@ Connectez ensuite Claude Desktop : Réglages → Développeur → Serveurs MCP
|
||||
locaux → **Modifier la config**, puis ajoutez dans `mcpServers` :
|
||||
|
||||
```json
|
||||
// macOS / Linux
|
||||
{
|
||||
"mcpServers": {
|
||||
"crowdlending-dev": {
|
||||
@@ -60,6 +61,28 @@ locaux → **Modifier la config**, puis ajoutez dans `mcpServers` :
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
// Windows
|
||||
{
|
||||
"mcpServers": {
|
||||
"crowdlending-dev": {
|
||||
"command": "cmd",
|
||||
"args": [
|
||||
"/c", "npx",
|
||||
"-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
|
||||
@@ -70,7 +93,16 @@ 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
|
||||
**Sous Windows, le wrapper `cmd /c` est obligatoire** (voir le second bloc
|
||||
ci-dessus) : `npx` y est en réalité `npx.cmd` (un script), et la façon dont
|
||||
Claude Desktop lance les process (`spawn` sans interpréteur de commandes) ne
|
||||
sait pas l'exécuter directement — sans ce wrapper, le serveur reste affiché
|
||||
comme « running » dans Claude Desktop mais ne répond jamais (blocage
|
||||
silencieux, pas d'erreur explicite). C'est un problème Node.js/Windows
|
||||
connu, pas spécifique à ce serveur — la config générée automatiquement dans
|
||||
Mon compte → Serveur MCP l'applique déjà si elle détecte Windows.
|
||||
|
||||
Notez aussi 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`.
|
||||
@@ -123,6 +155,9 @@ possible, même si les noms d'outils sont identiques des deux côtés.
|
||||
}
|
||||
```
|
||||
|
||||
Sous Windows, remplacez `"command": "npx"` par `"command": "cmd", "args": ["/c", "npx", ...]`
|
||||
sur chacune des deux entrées (voir Développement local plus haut).
|
||||
|
||||
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
|
||||
@@ -216,6 +251,12 @@ Garde-fous :
|
||||
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`.
|
||||
- **Le serveur reste sur « running » indéfiniment, « Preparing session… » puis
|
||||
« Could not attach »** — sous Windows, il manque le wrapper `cmd /c` (voir
|
||||
Développement local). C'est un problème de fond très courant : `npx` y est
|
||||
un script `.cmd` que `spawn()` ne sait pas exécuter directement, donc le
|
||||
process est lancé mais ne communique jamais réellement. Symptôme
|
||||
caractéristique : aucune erreur explicite, juste un blocage silencieux.
|
||||
- **`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
|
||||
|
||||
+24
-7
@@ -17,10 +17,11 @@
|
||||
* des outils de CETTE session uniquement (voir createSession). Deux sessions
|
||||
* ne partagent jamais d'état ni de données.
|
||||
*
|
||||
* Connexion depuis Claude Desktop (dev comme prod) :
|
||||
* { "url": "http://localhost:4100/mcp", "headers": { "X-API-Key": "..." } }
|
||||
* (remplacer l'URL par https://mcp.crowdlending.croguennec.net/mcp pour la
|
||||
* prod). Voir README.md pour le détail.
|
||||
* Connexion depuis Claude Desktop (dev comme prod) : ce fichier expose du
|
||||
* HTTP pur, mais claude_desktop_config.json n'accepte que des entrées
|
||||
* command/args — la connexion passe donc par le pont mcp-remote
|
||||
* (https://github.com/geelen/mcp-remote), voir README.md pour la config
|
||||
* exacte (et le wrapper cmd /c obligatoire sous Windows).
|
||||
*/
|
||||
|
||||
import { randomUUID } from 'node:crypto';
|
||||
@@ -63,6 +64,17 @@ const SESSION_IDLE_TIMEOUT_MS = 30 * 60 * 1000; // 30 min
|
||||
|
||||
console.error(`[crowdlending-mcp${LABEL ? `-${LABEL}` : ''}] démarrage — API cible : ${API_BASE}, hôtes autorisés : ${ALLOWED_HOSTS.join(', ')}, fetch_url : ${ENABLE_FETCH_URL ? 'activé' : 'désactivé'}`);
|
||||
|
||||
/** Préfixe commun à toutes les lignes de log applicatif. */
|
||||
const LOG_PREFIX = `[crowdlending-mcp${LABEL ? `-${LABEL}` : ''}]`;
|
||||
|
||||
/** Résumé lisible d'une requête JSON-RPC entrante (nom d'outil pour un
|
||||
* tools/call, méthode sinon), pour le log applicatif — jamais la clé API. */
|
||||
function describeRequest(body) {
|
||||
if (!body || typeof body !== 'object') return 'requête inconnue';
|
||||
if (body.method === 'tools/call') return `tools/call ${body.params?.name || '?'}`;
|
||||
return body.method || 'requête inconnue';
|
||||
}
|
||||
|
||||
/** Ajoute le libellé d'environnement au titre d'un outil (ex. "[PROD]"). */
|
||||
const withLabel = (title) => LABEL ? `${title} [${LABEL.toUpperCase()}]` : title;
|
||||
|
||||
@@ -118,7 +130,7 @@ setInterval(() => {
|
||||
const now = Date.now();
|
||||
for (const [sessionId, s] of sessions.entries()) {
|
||||
if (now - s.lastActivity > SESSION_IDLE_TIMEOUT_MS) {
|
||||
console.error(`[crowdlending-mcp${LABEL ? `-${LABEL}` : ''}] session ${sessionId} inactive depuis plus de 30 min, fermeture.`);
|
||||
console.error(`${LOG_PREFIX} session ${sessionId.slice(0, 8)} inactive depuis plus de 30 min, fermeture.`);
|
||||
s.transport.close();
|
||||
sessions.delete(sessionId);
|
||||
}
|
||||
@@ -179,7 +191,10 @@ app.post('/mcp', async (req, res) => {
|
||||
return;
|
||||
}
|
||||
touchSession(sessionId);
|
||||
const label = describeRequest(req.body);
|
||||
const startedAt = Date.now();
|
||||
await session.transport.handleRequest(req, res, req.body);
|
||||
console.error(`${LOG_PREFIX} session ${sessionId.slice(0, 8)} — ${label} — ${res.statusCode} (${Date.now() - startedAt}ms)`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -195,9 +210,11 @@ app.post('/mcp', async (req, res) => {
|
||||
}
|
||||
|
||||
const transport = await createSession(apiKey);
|
||||
const startedAt = Date.now();
|
||||
await transport.handleRequest(req, res, req.body);
|
||||
console.error(`${LOG_PREFIX} nouvelle session ${transport.sessionId ? transport.sessionId.slice(0, 8) : '?'} — initialize — ${res.statusCode} (${Date.now() - startedAt}ms)`);
|
||||
} catch (e) {
|
||||
console.error(`[crowdlending-mcp${LABEL ? `-${LABEL}` : ''}] erreur /mcp POST :`, e);
|
||||
console.error(`${LOG_PREFIX} erreur /mcp POST :`, e);
|
||||
if (!res.headersSent) res.status(500).json({ jsonrpc: '2.0', error: { code: -32603, message: e.message }, id: null });
|
||||
}
|
||||
});
|
||||
@@ -220,5 +237,5 @@ app.get('/mcp', handleExistingSession);
|
||||
app.delete('/mcp', handleExistingSession);
|
||||
|
||||
app.listen(PORT, '0.0.0.0', () => {
|
||||
console.error(`[crowdlending-mcp${LABEL ? `-${LABEL}` : ''}] à l'écoute sur le port ${PORT}`);
|
||||
console.error(`${LOG_PREFIX} à l'écoute sur le port ${PORT}`);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user