# MCP bug when subfolder-install in

**URL:** https://meta.discourse.org/t/mcp-bug-when-subfolder-install-in/402609
**Category:** Bug
**Tags:** fixed, mcp
**Created:** [May 10, 2026, 8:26pm UTC](https://meta.discourse.org/t/mcp-bug-when-subfolder-install-in/402609 "2026-05-10T20:26:42Z")
**Posts on this page:** 1
**Showing post:** 1

<div class="post-metadata">

### Author: ![janbolmeson](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/janbolmeson/32/192162_2.png) [@janbolmeson](https://meta.discourse.org/u/janbolmeson)
#### Post date: [May 10, 2026, 8:26pm UTC](https://meta.discourse.org/t/mcp-bug-when-subfolder-install-in/402609/1 "2026-05-10T20:26:42Z")

</div>

## `@discourse/mcp` fails on subfolder installs — leading-slash paths strip the site subpath

### TL;DR

On Discourse instances mounted at a subpath (e.g. `https://example.com/forum`), `@discourse/mcp` cannot connect because every internal API call drops the subpath, hitting the wrong host root. This breaks site validation and **every** subsequent tool call (`search`, `read_topic`, etc.), not just `--site` validation.

### Environment

- `@discourse/mcp` v0.2.7 (latest as of writing)
- Node via `npx -y @discourse/mcp@latest`
- Target: Discourse hosted at `https://<host>/forum` (subfolder install behind nginx)

### Steps to reproduce

1. Have a Discourse forum at a subpath, e.g. `https://example.com/forum`. Confirm `https://example.com/forum/about.json` returns `200`.
2. Run:

```bash
npx -y @discourse/mcp@latest --site https://example.com/forum --log_level debug

```

3. Send any MCP request (or just observe startup validation).

### Expected

Server validates against `https://example.com/forum/about.json` and tools call `https://example.com/forum/<endpoint>`.

### Actual

Debug log shows the request goes to the **host root** , not the subpath:

```plaintext
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

```

The `/forum` segment is silently dropped.

### Root cause

In `dist/http/client.js:42` (and the matching write path at `:85`):

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

```

Per the WHATWG URL spec, a `path` argument beginning with `/` is treated as **absolute** and replaces the base URL’s pathname. Throughout the codebase, paths are passed with a leading slash, e.g.:

- `dist/index.js:230` — `client.get('/about.json')`
- `dist/tools/builtin/select_site.js:15` — `client.get('/about.json')`
- All builtin tools follow the same `'/...'` pattern.

Result: `new URL('/about.json', 'https://example.com/forum')` → `https://example.com/about.json`. Subfolder is lost on every call.

### Suggested fix

Either (a) normalize in the HTTP client by stripping the leading slash from `path` and ensuring `this.base` has a trailing slash before resolution:

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

```

…or (b) change all call sites to use relative paths (no leading slash). Option (a) is safer — single point of change, no behavioural surprises elsewhere.

### Workaround for affected users

If your Discourse install also has a subdomain that 301-redirects to the subpath (e.g. `forum.example.com` → `example.com/forum/...`), pass the subdomain as `--site`. The MCP HTTP client follows redirects, so each call resolves to the correct subpath URL and authentication survives the hop. Confirmed working end-to-end (`initialize`, `search`, etc.) on `v0.2.7`.

If no such subdomain exists, there is currently no client-side workaround — the bug needs to be fixed in the package.

---

_[View the full topic](https://meta.discourse.org/t/mcp-bug-when-subfolder-install-in/402609)._
