upstash/context7 · error
proxy_error
proxy_error
Error message
Failed to proxy authorization server metadata
What it means
The MCP server proxies /.well-known/oauth-authorization-server metadata from the upstream authorization server. If fetching that metadata throws (network error, bad URL, non-JSON response), the handler responds 502 with error code "proxy_error". The first variant ("Failed to fetch authorization server metadata") is sent when fetch succeeded but metadata is missing/invalid.
Solutions
- Verify the authorization server URL configured in the MCP server env is correct and publicly reachable.
- Curl the upstream /.well-known/oauth-authorization-server endpoint to confirm it returns valid JSON.
- Retry after confirming the auth server is up (this is a 502 upstream outage).
- Check DNS/firewall/proxy settings on the host running the MCP server.
Example fix
// before AUTH_ISSUER=https://auth.internal.example // unreachable from MCP host // after AUTH_ISSUER=https://auth.example.com // publicly reachable, serves valid metadata
Defensive patterns
Strategy: retry
Validate before calling
const url = `${issuer.replace(/\/$/, '')}/.well-known/oauth-authorization-server`;
const ok = await fetch(url).then(r => r.ok).catch(() => false);
if (!ok) throw new Error(`Auth server metadata unreachable: ${url}`); Type guard
function isProxyError(res: unknown): res is { error: 'proxy_error'; message: string } {
return typeof res === 'object' && res !== null &&
(res as any).error === 'proxy_error';
} Try / catch
try {
metadata = await fetchAuthMetadata(issuer);
} catch (e) {
if (isProxyError(e?.body)) {
await sleep(backoff(attempt++));
metadata = await fetchAuthMetadata(issuer); // upstream outage, retry
} else throw e;
} Prevention
- Verify the AUTH_ISSUER URL is reachable from the MCP host before startup
- Add a readiness check that curls the well-known metadata endpoint
- Use a health-checked, HA auth server endpoint
- Alert on 502 proxy_error responses to catch auth-server outages early
When it happens
Trigger: GET the OAuth protected-resource/authorization-server metadata endpoint when the upstream auth server is unreachable, returns 5xx, or returns an unparseable body — the fetch/parse throws inside the route handler.
Common situations: Auth server temporarily down, misconfigured AUTH_ISSUER URL in server env, corporate network blocking the upstream host, or the issuer serving HTML instead of well-known JSON.
Related errors
- describeConnectionError(error, url)
- -32001
- await describeErrorResponse(response, fallback)
- Could not reach : )` : ""}\n
- err.error_description || err.error || "Device token poll…
AI-assisted analysis of upstash/context7@4416fb855b (2026-09-16).
Data as JSON: /api/errors/291d937bd09a42a3.
Report an issue: GitHub.
Appendix: source
Thrown at packages/mcp/src/index.ts:584
signal: abortSignal,
}),
async (response) => {
if (!response.ok) return { ok: false as const, status: response.status };
return { ok: true as const, metadata: await response.json() };
},
{ abortSignal }
);
if (!upstream.ok) {
console.error("[OAuth] Upstream error:", upstream.status);
return res.status(upstream.status).json({
error: "upstream_error",
message: "Failed to fetch authorization server metadata",
});
}
res.json(upstream.metadata);
} catch (error) {
console.error("[OAuth] Error fetching OAuth metadata:", error);
res.status(502).json({
error: "proxy_error",
message: "Failed to proxy authorization server metadata",
});
}
}
);
// OpenAI Apps SDK domain verification challenge
app.get(
"/.well-known/openai-apps-challenge",
(_req: express.Request, res: express.Response) => {
if (!OPENAI_APPS_CHALLENGE_TOKEN) {
return res.status(404).json({
error: "not_found",
message: "Endpoint not found.",
});
}
res.type("text/plain").send(OPENAI_APPS_CHALLENGE_TOKEN);View on GitHub (pinned to 4416fb855b)