@discourse/mcp échoue lors des installations dans un sous-dossier — les chemins avec slash initial suppriment le sous-chemin du site
TL;DR
Sur les instances Discourse montées dans un sous-chemin (par exemple https://example.com/forum), @discourse/mcp ne peut pas se connecter car chaque appel API interne perd le sous-chemin, pointant vers la racine incorrecte de l’hôte. Cela brise la validation du site et tous les appels d’outils suivants (search, read_topic, etc.), pas seulement la validation --site.
Environnement
@discourse/mcpv0.2.7 (dernière version au moment de la rédaction)- Node via
npx -y @discourse/mcp@latest - Cible : Discourse hébergé à
https://<host>/forum(installation dans un sous-dossier derrière nginx)
Étapes pour reproduire
- Avoir un forum Discourse dans un sous-chemin, par exemple
https://example.com/forum. Vérifier quehttps://example.com/forum/about.jsonrenvoie200. - Exécuter :
npx -y @discourse/mcp@latest --site https://example.com/forum --log_level debug - Envoyer n’importe quelle requête MCP (ou simplement observer la validation au démarrage).
Attendu
Le serveur valide contre https://example.com/forum/about.json et les outils appellent https://example.com/forum/<endpoint>.
Réel
Le journal de débogage montre que la requête va vers la racine de l’hôte, et non le sous-chemin :
DEBUG HTTP GET https://example.com/about.json
DEBUG HTTP GET https://example.com/about.json -> 403 Forbidden
ERROR Failed to validate --site https://example.com/forum: HTTP 403 Forbidden
Le segment /forum est silencieusement supprimé.
Cause racine
Dans dist/http/client.js:42 (et le chemin d’écriture correspondant à :85) :
const url = new URL(path, this.base).toString();
Selon la spécification WHATWG URL, un argument path commençant par / est traité comme absolu et remplace le nom de chemin de l’URL de base. Dans tout le code, les chemins sont transmis avec un slash initial, par exemple :
dist/index.js:230—client.get('/about.json')dist/tools/builtin/select_site.js:15—client.get('/about.json')- Tous les outils intégrés suivent le même motif
'/...'.
Résultat : new URL('/about.json', 'https://example.com/forum') → https://example.com/about.json. Le sous-dossier est perdu à chaque appel.
Correction suggérée
Soit (a) normaliser dans le client HTTP en supprimant le slash initial de path et en s’assurant que this.base a un slash final avant la résolution :
const base = this.base.toString().replace(/\/?$/, '/');
const rel = path.replace(/^\//, '');
const url = new URL(rel, base).toString();
Ou (b) modifier tous les sites d’appel pour utiliser des chemins relatifs (sans slash initial). L’option (a) est plus sûre — point unique de modification, aucune surprise comportementale ailleurs.
Contournement pour les utilisateurs affectés
Si votre installation Discourse possède également un sous-domaine qui effectue une redirection 301 vers le sous-chemin (par exemple forum.example.com → example.com/forum/...), passez le sous-domaine via --site. Le client HTTP MCP suit les redirections, donc chaque appel aboutit à l’URL correcte du sous-chemin et l’authentification survit au saut. Confirmé fonctionnel de bout en bout (initialize, search, etc.) sur v0.2.7.
Si un tel sous-domaine n’existe pas, il n’y a actuellement aucun contournement côté client — le bug doit être corrigé dans le package.