Problem
The dev/prod web backend protects every /api/* route with x-mcp-remote-auth: Bearer <MCP_INSPECTOR_API_TOKEN> (core/mcp/remote/node/server.ts:189-200). The browser only learns the token via ?MCP_INSPECTOR_API_TOKEN=… query string on first page load — clients/web/src/App.tsx:73-93 parses it and persists to sessionStorage.
Failure mode: if the user clears sessionStorage and reloads at the bare URL (no query string), every /api/* request 401s. Same problem if they load via a bookmark or hand-typed URL. No graceful recovery — the UI just fails silently when trying to connect to a server.
Steps to reproduce:
npm run dev, open the URL the banner prints.
- DevTools → Application → Session Storage → clear
MCP_INSPECTOR_API_TOKEN.
- Reload at
http://localhost:6274/ (drop the query string).
- Click connect on any server → handshake POST to
/api/mcp/send returns 401.
Proposed change
The server already knows the token at index.html serve time. Inject it into the page once so the browser doesn't depend on the query string surviving navigation.
Two options worth considering:
-
HTML template injection (preferred) — the vite-hono-plugin (and the prod server.ts) rewrites index.html on the / route to embed <script>window.__INSPECTOR_API_TOKEN__ = "…"</script>. App.tsx's getAuthToken() reads from window.__INSPECTOR_API_TOKEN__ ahead of the URL/sessionStorage fallback. Same-origin, no cookie semantics to reason about. Token is JS-accessible (same as today via sessionStorage), so no new XSS surface vs. the status quo.
-
HttpOnly cookie — server sets Set-Cookie: mcp_inspector_token=…; HttpOnly; Path=/; SameSite=Strict on the GET / response. Middleware accepts the token from the cookie OR the existing header. Browser fetches drop the Authorization/x-mcp-remote-auth plumbing (cookies sent automatically with credentials: "same-origin"). Slightly more robust against XSS, but it means changing the auth middleware and removing the header-setting code paths in core/mcp/remote/createRemoteTransport.ts and createRemoteFetch.ts.
Either way, keep the ?MCP_INSPECTOR_API_TOKEN=… query-string path working as a fallback for at least one release — there are scripts and integrations that already paste full URLs around.
Acceptance criteria
- Reloading at
http://localhost:6274/ (no query string, empty sessionStorage) loads the app and successfully calls /api/* without 401.
- The launcher banner URL still works for users who want to copy/paste it.
- The chosen path has an integration test exercising the
/ → first /api/* flow.
- AGENTS.md or the README mentions the new behavior so the next contributor isn't surprised.
Out of scope
Problem
The dev/prod web backend protects every
/api/*route withx-mcp-remote-auth: Bearer <MCP_INSPECTOR_API_TOKEN>(core/mcp/remote/node/server.ts:189-200). The browser only learns the token via?MCP_INSPECTOR_API_TOKEN=…query string on first page load —clients/web/src/App.tsx:73-93parses it and persists tosessionStorage.Failure mode: if the user clears sessionStorage and reloads at the bare URL (no query string), every
/api/*request 401s. Same problem if they load via a bookmark or hand-typed URL. No graceful recovery — the UI just fails silently when trying to connect to a server.Steps to reproduce:
npm run dev, open the URL the banner prints.MCP_INSPECTOR_API_TOKEN.http://localhost:6274/(drop the query string)./api/mcp/sendreturns 401.Proposed change
The server already knows the token at index.html serve time. Inject it into the page once so the browser doesn't depend on the query string surviving navigation.
Two options worth considering:
HTML template injection (preferred) — the vite-hono-plugin (and the prod
server.ts) rewritesindex.htmlon the/route to embed<script>window.__INSPECTOR_API_TOKEN__ = "…"</script>.App.tsx'sgetAuthToken()reads fromwindow.__INSPECTOR_API_TOKEN__ahead of the URL/sessionStorage fallback. Same-origin, no cookie semantics to reason about. Token is JS-accessible (same as today via sessionStorage), so no new XSS surface vs. the status quo.HttpOnly cookie — server sets
Set-Cookie: mcp_inspector_token=…; HttpOnly; Path=/; SameSite=Stricton theGET /response. Middleware accepts the token from the cookie OR the existing header. Browser fetches drop theAuthorization/x-mcp-remote-authplumbing (cookies sent automatically withcredentials: "same-origin"). Slightly more robust against XSS, but it means changing the auth middleware and removing the header-setting code paths incore/mcp/remote/createRemoteTransport.tsandcreateRemoteFetch.ts.Either way, keep the
?MCP_INSPECTOR_API_TOKEN=…query-string path working as a fallback for at least one release — there are scripts and integrations that already paste full URLs around.Acceptance criteria
http://localhost:6274/(no query string, empty sessionStorage) loads the app and successfully calls/api/*without 401./→ first/api/*flow.Out of scope