MAj MCP Serveur
This commit is contained in:
+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