MCP-Fehler bei Installation in Unterordner

@discourse/mcp schlägt bei Installationen in Unterordnern fehl — Pfade mit führendem Slash entfernen den Site-Unterpfad

TL;DR

Bei Discourse-Instanzen, die unter einem Unterpfad bereitgestellt werden (z. B. https://example.com/forum), kann sich @discourse/mcp nicht verbinden, da bei jedem internen API-Aufruf der Unterpfad entfernt wird und stattdessen die falsche Host-Wurzel angesprochen wird. Dies unterbricht die Site-Validierung und jeden nachfolgenden Tool-Aufruf (search, read_topic usw.), nicht nur die --site-Validierung.

Umgebung

  • @discourse/mcp v0.2.7 (Stand zum Zeitpunkt des Schreibens)
  • Node über npx -y @discourse/mcp@latest
  • Ziel: Discourse unter https://<host>/forum gehostet (Installation in Unterordner hinter nginx)

Schritte zur Reproduktion

  1. Stellen Sie ein Discourse-Forum unter einem Unterpfad bereit, z. B. https://example.com/forum. Stellen Sie sicher, dass https://example.com/forum/about.json mit 200 antwortet.
  2. Führen Sie Folgendes aus:
    npx -y @discourse/mcp@latest --site https://example.com/forum --log_level debug
    
  3. Senden Sie eine beliebige MCP-Anfrage (oder beobachten Sie einfach die Validierung beim Start).

Erwartet

Der Server validiert gegen https://example.com/forum/about.json, und Tools rufen https://example.com/forum/<endpoint> auf.

Tatsächliches Ergebnis

Das Debug-Protokoll zeigt, dass die Anfrage zur Host-Wurzel und nicht zum Unterpfad geht:

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

Das Segment /forum wird stillschweigend entfernt.

Ursache

In dist/http/client.js:42 (und dem entsprechenden Schreibpfad bei :85):

const url = new URL(path, this.base).toString();

Laut der WHATWG-URL-Spezifikation wird ein path-Argument, das mit / beginnt, als absolut behandelt und ersetzt den Pfad der Basis-URL. Im gesamten Codebase werden Pfade mit führendem Slash übergeben, z. B.:

  • dist/index.js:230client.get('/about.json')
  • dist/tools/builtin/select_site.js:15client.get('/about.json')
  • Alle integrierten Tools folgen demselben '/...'-Muster.

Ergebnis: new URL('/about.json', 'https://example.com/forum')https://example.com/about.json. Der Unterordner geht bei jedem Aufruf verloren.

Vorgeschlagene Lösung

Entweder (a) im HTTP-Client normalisieren, indem der führende Slash aus path entfernt wird und sichergestellt wird, dass this.base vor der Auflösung einen abschließenden Slash hat:

const base = this.base.toString().replace(/\/?$/, '/');
const rel  = path.replace(/^\//, '');
const url  = new URL(rel, base).toString();

…oder (b) alle Aufrufstellen so ändern, dass sie relative Pfade verwenden (ohne führenden Slash). Option (a) ist sicherer – nur ein einziger Änderungspunkt, keine unerwarteten Verhaltensänderungen anderswo.

Umgehungslösung für betroffene Nutzer

Wenn Ihre Discourse-Installation auch eine Subdomain hat, die mit 301 auf den Unterpfad weiterleitet (z. B. forum.example.comexample.com/forum/...), übergeben Sie die Subdomain als --site. Der MCP-HTTP-Client folgt Umleitungen, sodass jeder Aufruf die korrekte Unterpfad-URL auflöst und die Authentifizierung den Sprung übersteht. Auf v0.2.7 wurde dies end-to-end bestätigt (initialize, search usw.).

Wenn keine solche Subdomain existiert, gibt es derzeit keine clientseitige Umgehungslösung – der Fehler muss im Paket behoben werden.

1 „Gefällt mir“