@discourse/mcp falha em instalações em subpastas — caminhos com barra inicial removem o subcaminho do site
TL;DR
Em instâncias do Discourse montadas em um subcaminho (por exemplo, https://example.com/forum), o @discourse/mcp não consegue se conectar porque toda chamada interna à API remove o subcaminho, acessando a raiz errada do host. Isso quebra a validação do site e todas as chamadas de ferramenta subsequentes (search, read_topic, etc.), não apenas a validação de --site.
Ambiente
@discourse/mcpv0.2.7 (mais recente no momento da escrita)- Node via
npx -y @discourse/mcp@latest - Alvo: Discourse hospedado em
https://<host>/forum(instalação em subpasta atrás do nginx)
Passos para reproduzir
- Tenha um fórum do Discourse em um subcaminho, por exemplo,
https://example.com/forum. Confirme quehttps://example.com/forum/about.jsonretorna200. - Execute:
npx -y @discourse/mcp@latest --site https://example.com/forum --log_level debug - Envie qualquer solicitação MCP (ou apenas observe a validação na inicialização).
Esperado
O servidor valida contra https://example.com/forum/about.json e as ferramentas chamam https://example.com/forum/<endpoint>.
Realidade
O log de depuração mostra que a solicitação vai para a raiz do host, não para o subcaminho:
DEBUG HTTP GET https://example.com/about.json
DEBUG HTTP GET https://example.com/about.json -> 403 Forbidden
ERROR Falha ao validar --site https://example.com/forum: HTTP 403 Forbidden
O segmento /forum é silenciosamente removido.
Causa raiz
Em dist/http/client.js:42 (e no caminho de escrita correspondente em :85):
const url = new URL(path, this.base).toString();
Conforme a especificação WHATWG URL, um argumento path que começa com / é tratado como absoluto e substitui o pathname da URL base. Em todo o código, os caminhos são passados com uma barra inicial, por exemplo:
dist/index.js:230—client.get('/about.json')dist/tools/builtin/select_site.js:15—client.get('/about.json')- Todas as ferramentas integradas seguem o mesmo padrão
'/...'.
Resultado: new URL('/about.json', 'https://example.com/forum') → https://example.com/about.json. A subpasta é perdida em cada chamada.
Correção sugerida
Ou (a) normalizar no cliente HTTP removendo a barra inicial de path e garantindo que this.base tenha uma barra final antes da resolução:
const base = this.base.toString().replace(/\/?$/, '/');
const rel = path.replace(/^\//, '');
const url = new URL(rel, base).toString();
…ou (b) alterar todos os locais de chamada para usar caminhos relativos (sem barra inicial). A opção (a) é mais segura — ponto único de alteração, sem surpresas de comportamento em outros lugares.
Solução alternativa para usuários afetados
Se sua instalação do Discourse também tiver um subdomínio que redireciona 301 para o subcaminho (por exemplo, forum.example.com → example.com/forum/...), passe o subdomínio como --site. O cliente HTTP do MCP segue redirecionamentos, então cada chamada resolve para a URL correta do subcaminho e a autenticação sobrevive à transferência. Confirmado funcionando de ponta a ponta (initialize, search, etc.) na v0.2.7.
Se não houver tal subdomínio, atualmente não há solução alternativa do lado do cliente — o bug precisa ser corrigido no pacote.