fix: exempt loopback hosts from the CIMD metadata URL HTTPS requirement

`getCimdClientMetadataUrlError` rejected every non-HTTPS CIMD client metadata
URL with no loopback exemption, and the same check runs against `client.json`
on disk through `refineCimdMetadataUrl`, so it could not be worked around by
hand-editing the file either. Every test server in this repo speaks plain HTTP,
so CIMD could not be driven against any local fixture: #2242 shipped verified by
tests alone, and reproducing it by hand meant standing up a self-signed HTTPS
listener plus `NODE_TLS_REJECT_UNAUTHORIZED=0` in the test server's environment.

Accept plain `http:` on the three literals the SDK itself exempts from its
token-endpoint TLS assertion — `localhost`, `127.0.0.1` and `[::1]`. That is
option 1 in #2305 and matches what the runtime already tolerated:
`core/auth/cimd.ts` notes that an already-stored `client_id` may be an `http://`
URL used by local dev/test metadata servers. Anything outside those three,
`localhost.` and `tenant.app.localhost` included, is still rejected — matching
the SDK literal for literal keeps the two allow-lists from disagreeing about one
URL.

The exemption is a literal set rather than `isLoopbackHost` because
`core/client/config-parse.ts` is browser-safe and `core/node/hostUrl.ts` imports
`node:net`.

The field error now names the exemption instead of saying only "must use
HTTPS", and the form's hint and description say the same, so a developer
pointing the field at a local fixture is told which spellings work.

Closes #2305

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GfHQ8vMm5NBgzbUJ6UwxmB
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-09-11 02:31:47 -04:00
commit a1cad93ed9

View file

@ -560,16 +560,23 @@ from **Client settings**, not from a server's own OAuth settings. A `clientMetad
catalog entry's `oauth` block is silently ignored — and with `supportDCR: true` the connection then
succeeds *via DCR*, which looks like CIMD working until you read the client id.
⚠️ **The Inspector requires that URL to be HTTPS, and there is no loopback exemption**
**Use this server's own document as the `clientMetadataUrl`** — `/client-metadata.json` on the origin
the server announced on startup (`http://127.0.0.1:8092/client-metadata.json` when it got its
configured port; read the announced URL, since this fixture walks upward on `EADDRINUSE` like every
other one here). The Inspector requires HTTPS *except* on the three
loopback literals `localhost`, `127.0.0.1` and `[::1]`
(`getCimdClientMetadataUrlError` in `core/client/config-parse.ts`, applied to `client.json` on disk as
well as to the settings form). So this server's own `http://` document is **not** usable as a
`clientMetadataUrl`: it exists for the authorization-server side of the flow and for tests that drive
the AS directly. To drive the Inspector end to end you need the document served over HTTPS —
`https://127.0.0.1:8443/client-metadata.json` from a throwaway self-signed listener works, with
`NODE_TLS_REJECT_UNAUTHORIZED=0` in the *test server's* environment so its own fetch of that document
succeeds. That asymmetry is tracked in
[#2305](https://github.com/modelcontextprotocol/inspector/issues/2305); it is the same over-narrow
allow-list shape as the token-endpoint exemption above.
well as to the settings form), which is the same exemption the SDK applies to token endpoints and what
the runtime already tolerated for an already-stored `client_id`. Give the URL the host the server is
actually listening on; a host outside those three — `localhost.` and `tenant.app.localhost` included,
even though both resolve to loopback — is still rejected, deliberately, so this allow-list and the
SDK's cannot disagree about one URL.
⚠️ **Before [#2305](https://github.com/modelcontextprotocol/inspector/issues/2305) there was no
loopback exemption at all**, so driving this flow meant standing up a throwaway self-signed HTTPS
listener to hold the document and setting `NODE_TLS_REJECT_UNAUTHORIZED=0` in the *test server's*
environment so its own fetch of that document would succeed. That workaround is no longer needed — if
you find it in a script or an older note, delete it.
With that in place: set the metadata URL in Client settings, connect, and open **Connection Info**.
It should read `Client registration — Client ID Metadata (CIMD)` with the **client id equal to the