Error MCP al instalar en subcarpeta en

@discourse/mcp falla en instalaciones en subcarpetas: las rutas con barra inicial eliminan la subruta del sitio

Resumen rápido

En las instancias de Discourse montadas en una subruta (p. ej. https://ejemplo.com/foro), @discourse/mcp no puede conectarse porque cada llamada interna a la API elimina la subruta, accediendo incorrectamente a la raíz del host. Esto rompe la validación del sitio y todas las llamadas subsiguientes a herramientas (search, read_topic, etc.), no solo la validación de --site.

Entorno

  • @discourse/mcp v0.2.7 (la última al momento de escribir esto)
  • Node mediante npx -y @discourse/mcp@latest
  • Objetivo: Discourse alojado en https://<host>/foro (instalación en subcarpeta detrás de nginx)

Pasos para reproducir

  1. Ten un foro de Discourse en una subruta, por ejemplo https://ejemplo.com/foro. Confirma que https://ejemplo.com/foro/about.json devuelva 200.
  2. Ejecuta:
    npx -y @discourse/mcp@latest --site https://ejemplo.com/foro --log_level debug
    
  3. Envía cualquier solicitud MCP (o simplemente observa la validación al iniciar).

Comportamiento esperado

El servidor debe validarse contra https://ejemplo.com/foro/about.json y las herramientas deben llamar a https://ejemplo.com/foro/<endpoint>.

Comportamiento real

El registro de depuración muestra que la solicitud va a la raíz del host, no a la subruta:

DEBUG HTTP GET https://ejemplo.com/about.json
DEBUG HTTP GET https://ejemplo.com/about.json -> 403 Forbidden
ERROR Error al validar --site https://ejemplo.com/foro: HTTP 403 Forbidden

El segmento /foro se elimina silenciosamente.

Causa raíz

En dist/http/client.js:42 (y en la ruta de escritura correspondiente en :85):

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

Según la especificación WHATWG de URL, un argumento path que comienza con / se trata como absoluto y reemplaza la ruta de la URL base. En todo el código, las rutas se pasan con una barra inicial, por ejemplo:

  • dist/index.js:230client.get('/about.json')
  • dist/tools/builtin/select_site.js:15client.get('/about.json')
  • Todas las herramientas integradas siguen el mismo patrón '/...'.

Resultado: new URL('/about.json', 'https://ejemplo.com/foro')https://ejemplo.com/about.json. La subcarpeta se pierde en cada llamada.

Solución sugerida

O bien (a) normalizar en el cliente HTTP eliminando la barra inicial de path y asegurando que this.base tenga una barra final antes de la resolución:

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

…o (b) cambiar todos los puntos de llamada para usar rutas relativas (sin barra inicial). La opción (a) es más segura: un único punto de cambio y sin comportamientos inesperados en otras partes.

Solución temporal para usuarios afectados

Si tu instalación de Discourse también tiene un subdominio que redirige con 301 a la subruta (p. ej. foro.ejemplo.comejemplo.com/foro/...), pasa el subdominio como --site. El cliente HTTP de MCP sigue las redirecciones, por lo que cada llamada se resuelve a la URL correcta de la subruta y la autenticación sobrevive al salto. Funciona de extremo a extremo (initialize, search, etc.) confirmado en v0.2.7.

Si no existe tal subdominio, actualmente no hay solución temporal del lado del cliente: el error debe corregirse en el paquete.

1 me gusta