[BUG] MCP OAuth discovery (.well-known) fails with InvalidHTTPResponse across multiple servers

Status Open
Reported on v2.1.251
Maintainer reply None cached
Activity 4 comments · opened Sep 24, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Authenticating any remote MCP server that uses OAuth discovery fails consistently with "InvalidHTTPResponse" when the client fetches the server's .well-known discovery document (either oauth-authorization-server or oauth-protected-resource, depending on the server).

This happens with every OAuth-based remote MCP server tried, not one specific one:

The failure is not caused by network, DNS, or configuration issues (see reproduction steps and ruled-out causes below).

What Should Happen?

The MCP server should authenticate successfully via OAuth, and its tools should become available for use.

Error Messages/Logs

SDK auth failed: InvalidHTTPResponse fetching https://airtable.com/.well-known/oauth-authorization-server/oauth2/v1 . For more information, pass `verbose: true` in the second argument to fetch()

SDK auth failed: InvalidHTTPResponse fetching https://mcp.make.com/.well-known/oauth-protected-resource . For more information, pass `verbose: true` in the second argument to fetch()

InvalidHTTPResponse fetching https://mcp.airtable.com/.well-known/oauth-protected-resource . For more information, pass `verbose: true` in the second argument to fetch()

Steps to Reproduce

  1. In the Claude Code VS Code extension, open the "MCP servers" panel.
  2. Add a remote MCP server using "HTTP (remote)" transport with an official, verified OAuth-based MCP URL (e.g. https://mcp.airtable.com/mcp for Airtable, or https://mcp.make.com for Make), scope "Local".
  3. Click "Add server", then click into the newly added server and click "Authenticate" (or "Reconnect").
  4. The server shows status "Failed" / "Needs Auth", and the error above appears.

This was reproduced with 3 different OAuth-based remote MCP servers (Airtable, Make, and Airtable again after fully removing and re-adding it from scratch with the confirmed-correct official URL), so it is not specific to one server or one misconfigured URL.

Ruled out as causes:

  • Wrong/misconfigured server URL (reproduced even after re-adding Airtable from scratch using its officially documented URL from support.airtable.com)
  • Local network/DNS/firewall issues (reproduced identically on a completely different network — home Wi-Fi vs a 5G mobile hotspot)
  • Stale local state (reproduced after "Developer: Reload Window" in VS Code, and after a full PC reboot)
  • Provider-side outage (Airtable's own status page, status.airtable.com, shows "All Systems Operational", no incidents in the prior 15 days)

Claude Model

Not sure / Multiple models

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.1.251

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

VS Code integrated terminal

Additional Information

Searched existing issues before filing — found no open issue matching this exact error. One closed, possibly related issue was found: #46879 ("Streamable HTTP MCP: auth requirement should be based on 401 response, not well-known endpoint discovery"), which discusses the same underlying .well-known-based auth discovery mechanism, though its relevance to this specific error was not independently confirmed.

View original on GitHub ↗

3 Comments

stonianua · 14 days ago

InvalidHTTPResponse on the .well-known fetch usually means the OAuth client got a response it could not treat as a discovery document (non-2xx, empty body, HTML challenge/login page, wrong Content-Type, or JSON that fails schema parse) — not that DNS/network failed. Your matrix (Airtable + Make, two networks, reload + reboot) already points away from “one bad URL” and toward the VS Code MCP auth path’s discovery fetch.

A few checks that have narrowed this class of failure:

  1. Capture the raw discovery response once — From the same Windows box, hit the exact URLs in the error with curl -i (or VS Code’s network log if you can surface it):
  • https://mcp.airtable.com/.well-known/oauth-protected-resource
  • https://airtable.com/.well-known/oauth-authorization-server/oauth2/v1 (or whatever issuer path the first document advertises)
  • https://mcp.make.com/.well-known/oauth-protected-resource

Note status, Content-Type, and whether the body is JSON vs HTML/redirect. If curl gets clean JSON 200 while Claude Code still throws InvalidHTTPResponse, the bug is almost certainly in how the extension’s fetch/parse path handles that response (redirects, TLS/proxy, Accept headers), not the MCP host being down.

  1. Watch for path-join / issuer quirks — The Airtable authorization-server URL in your log (…/oauth-authorization-server/oauth2/v1) is a valid path-based issuer shape under RFC 8414, but a client that double-appends path segments or follows a soft redirect to an HTML page will surface exactly as InvalidHTTPResponse. Comparing the resource / authorization_servers fields from the protected-resource document against the URL that actually fails is a quick tell.
  1. Regression bisect signal — You marked this as a regression on 2.1.251. If you still have a prior build that worked, one authenticate attempt there vs 2.1.251 with --verbose (or whatever surfaces the underlying fetch error) often shows whether the client started rejecting a previously tolerated status/body (e.g. application/jose / charset variants / 304) or changed which well-known URL it constructs.
  1. Related prior art — #46879 discusses auth gating driven by well-known discovery rather than a 401 from the MCP endpoint; worth linking if your curl shows the resource is fine but discovery is what the client insists on first.

For maintainers: Claude Code VS Code 2.1.251, Windows, HTTP remote MCP, OAuth servers Airtable + Make, error InvalidHTTPResponse on both oauth-protected-resource and oauth-authorization-server URLs, repro after clean re-add + network change. Ideal fix path: surface status + content-type + first bytes of body in the UI error instead of only InvalidHTTPResponse.

Happy to compare curl -i dumps if you paste one failed well-known response (redact tokens).

Caetanogp · 11 days ago

Thanks for the detailed breakdown — ran the curl checks you suggested.

https://mcp.airtable.com/.well-known/oauth-protected-resource (the URL in the original error):

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Clean, well-formed JSON body (resource, authorization_servers, scopes_supported, etc.) — nothing malformed, no redirect, no HTML. This matches your first hypothesis: curl gets a clean 200 while Claude Code still throws InvalidHTTPResponse, so the bug looks like it's in the extension's fetch/parse path, not the server being down.

Authorization-server discovery for the issuer Airtable advertises (https://airtable.com/oauth2/v1) — tested both RFC 8414 URL shapes:

Path-insertion (.well-known inserted before the issuer's path): https://airtable.com/.well-known/oauth-authorization-server/oauth2/v1 → 200 OK, clean JSON (issuer, authorization_endpoint, token_endpoint, etc. all present and correct).
Path-appending (.well-known appended after the issuer's path): https://airtable.com/oauth2/v1/.well-known/oauth-authorization-server → 404 Not Found, Content-Type: text/html, ~304KB body — Airtable's normal web-app 404 page, not an error JSON.
This lines up with your second hypothesis exactly ("path-join / issuer quirks"). If the client is constructing the discovery URL with the wrong RFC 8414 shape for an issuer that has a non-root path (/oauth2/v1 rather than just /), it would hit that 404 HTML page while expecting JSON — which would plausibly surface as InvalidHTTPResponse.

So: Airtable's endpoints themselves look healthy on both checks. The evidence points at the client either mishandling the first (otherwise-clean) response, or constructing the second discovery URL with the wrong path-join convention when the issuer path isn't root.

Update — found a related, but distinct, server-side bug while testing a second MCP provider

While investigating something unrelated, hit the identical InvalidHTTPResponse error on Upwork's newly-launched official MCP server (mcp.upwork.com):

SDK auth failed: InvalidHTTPResponse fetching https://mcp.upwork.com/.well-known/oauth-protected-resource/mcp
Unlike the Airtable case above, here the URL quoted in the error (note the /mcp suffix — this is the Protected Resource Metadata endpoint, RFC 9728, a different well-known doc than the Authorization Server Metadata ones discussed above) does reproduce as broken in curl:

$ curl -o /dev/null -w "HTTP=%{http_code} SIZE=%{size_download} EXIT=%{exitcode}\n" https://mcp.upwork.com/.well-known/oauth-protected-resource/mcp
HTTP=200 SIZE=0 EXIT=56
200 OK headers claimed, but 0 bytes delivered — connection reset mid-response (CURLE_RECV_ERROR). Reproduced twice, consistent both times. The root shape without the /mcp suffix (https://mcp.upwork.com/.well-known/oauth-protected-resource) works fine (200, clean 159-byte JSON).

Checked whether this was Claude Code guessing the wrong shape, or following the server's own hint — it's the latter:

$ curl -i https://mcp.upwork.com/mcp
HTTP/1.1 401 Unauthorized
www-authenticate: Bearer error="invalid_token", ..., resource_metadata="https://mcp.upwork.com/.well-known/oauth-protected-resource/mcp"
Upwork's own server advertises, via the standard WWW-Authenticate challenge, exactly the URL that's broken. So this specific failure is server-side on Upwork's end, not a client path-construction choice.

Also re-tested Airtable's own Protected Resource Metadata endpoint (same RFC 9728 doc type, separate from the Authorization Server Metadata shapes discussed above) and found the identical failure signature there too:

https://mcp.airtable.com/.well-known/oauth-protected-resource → 200, clean JSON, 378 bytes
https://mcp.airtable.com/.well-known/oauth-protected-resource/mcp → 200 headers claimed, 0 bytes, connection reset (same as Upwork)
To be clear about scope: this doesn't resolve the original mystery above (the exact root-shape URL from the original Airtable error still reproduces as healthy in curl while failing in Claude Code — that discrepancy stands as-is). What it does show is a second, independently-confirmed bug pattern — a path-suffixed Protected Resource Metadata URL that returns success headers but resets the connection with zero bytes — present on two unrelated providers (Airtable and Upwork), with Upwork's own server explicitly advertising the broken URL via its WWW-Authenticate header. Worth Claude Code hardening its error reporting for this case regardless (a 0-byte/reset response surfacing as an opaque InvalidHTTPResponse is hard to debug from the client side alone).

Environment: Windows, Claude Code 2.1.251+ (still reproducing as of today, now also confirmed against a second, independent MCP provider), HTTP remote MCP.

pfreude · 9 days ago

Correction (same day): this was not a Claude Code regression in our case. 2.1.285 installed side by side fails the same way now. The cause was local TLS interception: Norton Antivirus "Web/Mail Shield" re-signs HTTPS on this machine (the leaf for our MCP host is issued by CN=Norton Web/Mail Shield Root). Claude Code's HTTP client then reports InvalidHTTPResponse on the proxied reply, while Node's fetch reads the same reply without trouble. Other remote HTTP MCP servers fail from Claude Code on the same machine too. If you see InvalidHTTPResponse from a Windows machine, check the certificate issuer for an antivirus or TLS-scanning proxy before anything else. The client could surface the underlying parse error instead of the bare InvalidHTTPResponse, which would make this much easier to diagnose.

<details><summary>Original comment (superseded)</summary>

Another data point, possibly the same root cause: it also hits servers that use a static bearer token (no OAuth). The server log showed the client's POST /mcp answered 200 OK while the client reported InvalidHTTPResponse fetching "https://<host>"; Node's fetch from the same machine worked.
</details>

Showing cached comments. Read the full discussion on GitHub ↗