diff --git a/mcpjam-inspector/server/routes/web/__tests__/chat-v2.hosted.test.ts b/mcpjam-inspector/server/routes/web/__tests__/chat-v2.hosted.test.ts index bb9bed7e7..e26f6d3e9 100644 --- a/mcpjam-inspector/server/routes/web/__tests__/chat-v2.hosted.test.ts +++ b/mcpjam-inspector/server/routes/web/__tests__/chat-v2.hosted.test.ts @@ -296,9 +296,15 @@ describe("web routes — chat-v2 hosted mode", () => { "https://example.convex.site/web/authorize-batch", expect.objectContaining({ method: "POST", + // `localRuntime: true` is set whenever HOSTED_MODE is false (the + // default in tests — VITE_MCPJAM_HOSTED_MODE is not "true" here). + // Convex uses it to skip the HTTPS-only check on MCP server URLs + // for local Inspector callers; see normalizeAuthorizeResult in + // mcpjam-backend/convex/http.ts. body: JSON.stringify({ projectId: "project-1", serverIds: ["server-1", "server-2"], + localRuntime: true, }), }) ); diff --git a/mcpjam-inspector/server/routes/web/auth.ts b/mcpjam-inspector/server/routes/web/auth.ts index 071b9b758..acb019454 100644 --- a/mcpjam-inspector/server/routes/web/auth.ts +++ b/mcpjam-inspector/server/routes/web/auth.ts @@ -11,7 +11,7 @@ import type { RpcLogger, UnauthorizedRefreshHandler, } from "@mcpjam/sdk"; -import { WEB_CALL_TIMEOUT_MS } from "../../config.js"; +import { HOSTED_MODE, WEB_CALL_TIMEOUT_MS } from "../../config.js"; import { attachHostedRpcLogs, createHostedRpcLogCollector, @@ -397,6 +397,18 @@ export async function authorizeBatch( ...(typeof options?.accessVersion === "number" ? { accessVersion: options.accessVersion } : {}), + // Skip Convex's hosted-mode HTTPS-only check on MCP server URLs + // when this Inspector instance is running locally. Convex doesn't + // open MCP server URLs itself (we do, from this Hono backend), so + // an `http://localhost` URL is harmless metadata in that case. + // + // Convex only honors `localRuntime` when the request has no + // browser Origin, so a hosted browser at app.mcpjam.com can't + // smuggle it in to bypass the policy. The flag itself isn't + // Inspector-specific — any non-browser caller can set it — see + // the docstring on `normalizeAuthorizeResult` in + // mcpjam-backend/convex/http.ts for the full rationale. + ...(!HOSTED_MODE ? { localRuntime: true } : {}), }), }); } catch (error) {