{"record":{"id":"4a6134dca7fd777d","repo":"different-ai/openwork","slug":"mcp-http-html-response","errorCode":"MCP_HTTP_HTML_RESPONSE","errorMessage":"MCP_HTTP_HTML_RESPONSE","messagePattern":"MCP_HTTP_HTML_RESPONSE","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ee/apps/den-api/src/capability-sources/external-mcp-diagnostics.ts","lineNumber":986,"sourceCode":"        operatorAction: \"Grant the provider role, ACL, or application permission required for this operation.\",\n      }\n    }\n  }\n  if (status >= 400) {\n    return {\n      phase,\n      category: \"http_failure\",\n      code: `MCP_HTTP_${status}`,\n      retryable: status === 408,\n      actionOwner: \"provider_admin\",\n      operatorAction: \"Inspect provider and proxy logs for the failing HTTP request using the diagnostic reference.\",\n    }\n  }\n  if (phase.startsWith(\"MCP_\") && input.contentType === \"text/html\") {\n    return {\n      phase: \"HTTP_ROUTING\",\n      category: \"unexpected_html\",\n      code: \"MCP_HTTP_HTML_RESPONSE\",\n      retryable: false,\n      actionOwner: \"organization_admin\",\n      operatorAction: \"Verify the MCP path is not a sign-in page, portal route, or proxy-generated HTML response.\",\n    }\n  }\n  if (phase === \"MCP_INITIALIZED\" && (status === 202 || status === 204)) return null\n  if (phase.startsWith(\"MCP_\") && input.contentType !== \"application/json\" && input.contentType !== \"text/event-stream\") {\n    return {\n      phase: \"MCP_TRANSPORT\",\n      category: \"unexpected_content_type\",\n      code: \"MCP_HTTP_CONTENT_TYPE\",\n      retryable: false,\n      actionOwner: \"provider_admin\",\n      operatorAction: \"Return an MCP JSON or event-stream response with a standards-compliant Content-Type header.\",\n    }\n  }\n  return null\n}","sourceCodeStart":968,"sourceCodeEnd":1004,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-api/src/capability-sources/external-mcp-diagnostics.ts#L968-L1004","documentation":"MCP_HTTP_HTML_RESPONSE is raised when an MCP-phase request returns a response whose Content-Type is text/html. The classifier maps this to HTTP_ROUTING / unexpected_content_type: the URL is reachable, but it is serving an HTML page instead of the MCP JSON/event-stream protocol — almost always a sign-in page, portal route, or proxy-generated error page sitting at the MCP path. Non-retryable, owned by the organization admin.","triggerScenarios":"Any request in an MCP_ phase where input.contentType === 'text/html'. Classic cases: an SSO gateway intercepting the MCP path and returning a login page, a proxy returning its HTML 502/error page, or the configured URL pointing at a web portal route instead of the MCP endpoint.","commonSituations":"Provider behind SSO where the MCP route requires a session cookie and unauthenticated requests get the login HTML; corporate proxies replacing upstream errors with branded HTML; misconfigured reverse proxy routing /mcp to a SPA fallback index.html.","solutions":["Verify the MCP path is not a sign-in page, portal route, or proxy-generated HTML response by inspecting the returned HTML.","Correct the configured endpoint URL or add the authentication the proxy/SSO requires so the MCP handler is reached.","Fix the reverse proxy/SPA fallback so /mcp routes to the MCP server rather than the HTML index."],"exampleFix":"// before: SPA fallback catches /mcp\napp.get('*', () => sendFile('index.html'))\n// after: MCP path excluded from the fallback\napp.use('/mcp', mcpServer)\napp.get('*', () => sendFile('index.html'))","handlingStrategy":"validation","validationCode":"// verify the endpoint returns an MCP content type before wiring it up\nconst probe = await fetch(mcpUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: initializeBody })\nconst ct = probe.headers.get('content-type') ?? ''\nif (ct.includes('text/html')) throw new Error(`${mcpUrl} serves HTML (sign-in/portal/proxy page), not MCP`) ","typeGuard":"function isHtmlResponse(d: { code: string }): boolean {\n  return d.code === 'MCP_HTTP_HTML_RESPONSE'\n}","tryCatchPattern":"try {\n  return await client.initialize(mcpUrl)\n} catch (e) {\n  if (isHtmlResponse(e.diagnostic)) {\n    // non-retryable: inspect the HTML body (login page? proxy error?) and fix routing/auth\n    throw new Error(`HTML page at MCP path — check SSO/proxy for ${mcpUrl}`)\n  }\n  throw e\n}","preventionTips":["Confirm the MCP route bypasses SSO/login redirects (service accounts, IP allowlists, or token auth at the proxy).","Exclude API/MCP paths from SPA fallback and HTML error-page middleware on reverse proxies.","Probe the endpoint's Content-Type as part of configuration validation."],"tags":["mcp","content-type","html","routing","sso"],"backgroundTag":"html-instead-of-json","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}