@discourse/mcp가 서브폴더 설치 환경에서 실패 — 슬래시(/)로 시작하는 경로가 사이트 서브패스를 제거함
요약
서브패스에 마운트된 Discourse 인스턴스(예: https://example.com/forum)에서 @discourse/mcp는 모든 내부 API 호출에서 서브패스가 누락되어 잘못된 호스트 루트를 호출하기 때문에 연결할 수 없습니다. 이로 인해 사이트 검증과 모든 후속 도구 호출(search, read_topic 등)이 --site 검증뿐만 아니라 모두 중단됩니다.
환경
@discourse/mcpv0.2.7 (작성 시점 기준 최신 버전)npx -y @discourse/mcp@latest를 통해 실행되는 Node- 대상: nginx 뒤의 서브폴더 설치로 호스팅된
https://<host>/forum의 Discourse
재현 단계
- 서브패스에 Discourse 포럼을 설정합니다. 예:
https://example.com/forum.https://example.com/forum/about.json이200을 반환하는지 확인합니다. - 다음을 실행합니다:
npx -y @discourse/mcp@latest --site https://example.com/forum --log_level debug - MCP 요청을 보내거나(또는 시작 시 검증만 관찰합니다).
기대 동작
서버가 https://example.com/forum/about.json에 대해 검증하고, 도구들이 https://example.com/forum/<endpoint>를 호출해야 합니다.
실제 동작
디버그 로그는 요청이 서브패스가 아닌 호스트 루트로 전송되고 있음을 보여줍니다:
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
/forum 세그먼트가 조용히 제거됩니다.
근본 원인
dist/http/client.js:42(그리고 :85의 일치하는 쓰기 경로)에서:
const url = new URL(path, this.base).toString();
WHATWG URL 사양에 따르면 /로 시작하는 path 인자는 절대 경로로 처리되어 기본 URL의 pathname을 대체합니다. 코드베이스 전반에서 경로는 앞선 슬래시를 포함하여 전달되며, 예를 들어:
dist/index.js:230—client.get('/about.json')dist/tools/builtin/select_site.js:15—client.get('/about.json')- 모든 내장 도구가 동일한
'/...'패턴을 따릅니다.
결과적으로: new URL('/about.json', 'https://example.com/forum') → https://example.com/about.json. 모든 호출에서 서브폴더가 손실됩니다.
제안된 수정 사항
(a) HTTP 클라이언트에서 path의 앞선 슬래시를 제거하고 해석 전에 this.base에 뒤따르는 슬래시가 있는지 확인하여 정규화하거나:
const base = this.base.toString().replace(/\/?$/, '/');
const rel = path.replace(/^\//, '');
const url = new URL(rel, base).toString();
…또는 (b) 모든 호출 지점을 상대 경로(앞선 슬래시 없음)를 사용하도록 변경하십시오. 옵션 (a)가 더 안전합니다 — 변경 지점이 단 하나이며 다른 곳에서 동작상의 문제가 발생하지 않습니다.
영향 받는 사용자를 위한 우회 방법
Discourse 설치 환경에 서브패스로 301 리다이렉트되는 서브도메인이 있는 경우(예: forum.example.com → example.com/forum/...), 서브도메인을 --site로 전달하십시오. MCP HTTP 클라이언트는 리다이렉트를 따르기 때문에 각 호출이 올바른 서브패스 URL로 해석되고 인증이 홉을 거치더라도 유지됩니다. v0.2.7에서 initialize, search 등이 끝-to-끝으로 정상 작동하는 것이 확인되었습니다.
이러한 서브도메인이 없다면 현재 클라이언트 측 우회 방법은 없습니다 — 이 버그는 패키지 내에서 수정되어야 합니다.