Send Render's pre-registered OAuth client ID - #2
Merged
Conversation
Clean-room testing found that the default auth path cannot work for anyone. A
first run with no credentials fails at startup with:
MCP: Failed to connect to render: Incompatible auth server: does not support
dynamic client registration — probe: endpoint returned an untyped response
(401) — this URL does not appear to speak MCP
Render's MCP server advertises its authorization server correctly, but that
server (https://api.render.com) publishes only authorization_code and
refresh_token grants with S256 PKCE, and no registration_endpoint. Dynamic
client registration is impossible against it.
pi-mcp-adapter attempts registration precisely when `oauth.clientId` is omitted,
and buildRenderMcpConfig omitted it. Render instead pre-registers one public PKCE
client per integration, which is why the Claude Code plugin ships
`oauth.clientId: "claude"`. This package needs the equivalent.
Send `oauth.clientId: "pi"` on the OAuth path and leave the bearer path alone,
since it never runs an OAuth flow. The ID is public and carries no secret.
SPEC §5 already described the mechanism — "the adapter performs dynamic client
registration when `oauth.clientId` is omitted" — but concluded that this matched
the Claude Code plugin, which is the one case that does not rely on
registration. Correct that reasoning and mark the field required.
Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Found during T-1 clean-room testing. Draft: must not merge until the
piclient ID is confirmed registered on Render's side — see the gate below.The defect
v0.1.0's default and recommended auth path cannot work for anyone. A first run with no credentials fails at startup:
Cause
Render's MCP server advertises OAuth correctly:
mcp.render.com/.well-known/oauth-protected-resourcereturns 200 and nameshttps://api.render.comas the authorization server. But that server's metadata publishes onlyauthorization_codeandrefresh_tokenwith S256 PKCE and noregistration_endpoint, so dynamic client registration is impossible.pi-mcp-adapterattempts registration precisely whenoauth.clientIdis omitted, andbuildRenderMcpConfigomitted it. Render instead pre-registers one public PKCE client per integration —claude,cursor,codex— which is why the Claude Code plugin shipsoauth.clientId: "claude"rather than relying on registration.This is the same gap
misc/kimi-plugin-spec.md§4.2 documented for Kimi, with the same root cause.Change
Send
oauth.clientId: "pi"on the OAuth path. The bearer path is untouched, since it never runs an OAuth flow. The ID is public and carries no client secret.docs/SPEC.md§5 already described the mechanism accurately — "the adapter performs dynamic client registration whenoauth.clientIdis omitted" — but concluded it matched the Claude Code plugin, the one case that does not rely on registration. That reasoning is corrected and the field is marked required.Merge gate
piforhttps://mcp.render.com/mcp. If the registered ID differs, change the constant to match.redirectUri, which suggests it does; if not, addoauth.redirectUri./mcp-auth render, then list services.Verification so far
npm run verifypasses with 67 tests (64 before, plus 3). The new unit tests assert the client ID is present on the OAuth path, absent on the bearer path, and that no client secret is ever serialized.tests/extension/loads.test.tspins the exact adapter config, so it caught this change and was updated deliberately.Not yet verified: the live OAuth flow, which is what the merge gate covers.