Repository navigation
release: MCP DCR + consent-proxy clientid fixes → PROD (#2709 #2710 #2711) - #2712
Merged
Merged
Conversation
…ients Reverses the incorrect unification from #2700. DEV and PROD each have their OWN tutorials-identity service instance with a DISTINCT clientid: - DEV = 0b1e8b56-5f5d-4ebf-a9e9-28aae2964236 - PROD = 5a7cb5fd-a0f0-4678-8f51-f8c471e0ab34 #2700 wrongly claimed a single shared client (0b1e8b56…) for both envs. That is why PROD failed live with "server rejected a token it had just issued": the interactive id_token's aud = the supplied client_id (0b1e8b56…), but PROD's tutorials-srv-mcp validates aud against its OWN instance clientid (5a7cb5fd…) → WrongAudience 401 after a successful browser login. Proven on PROD 2026-10-11: an M2M JWT (aud=5a7cb5fd…) returns 200 on /mcp-auth/api, and the interactive flow with client_id=5a7cb5fd… now connects end-to-end. Also fixed in IAS console (config, not code): added https://developers.sap.com/mcp-oauth/callback to the PROD client (5a7cb5fd…, app 8164289a…) redirect URIs — it had only the loopback callbacks. (The earlier #2667-era addition had gone onto the DEV client by mistake.) Updates: env table (Production→5a7cb5fd…, Dev→0b1e8b56…), both mcp-remote JSON snippets (default to PROD id), and the prose (distinct per-env clients, how to read each env's clientid). Doc-only; no code change.
…d-doc docs(mcp): correct PROD client_id — DEV and PROD have DISTINCT IAS clients
Native-HTTP OAuth MCP clients (Claude Code/Desktop, Joule Work Desktop) bootstrap via DCR — they POST to a registration_endpoint to get a client_id. The consent proxy had none (discovery registration_endpoint=null, POST /mcp-oauth/register 404), so the advertised "native HTTP, no bridge" path failed; the only working path was the mcp-remote bridge with an explicit, env-specific client_id (DEV 0b1e8b56…, PROD 5a7cb5fd…) — the fragility behind the multi-day PROD aud-mismatch saga. Add a facade DCR endpoint. /mcp-oauth/register returns THIS environment's existing tutorials-identity public PKCE client_id, read from the bound VCAP_SERVICES.identity[].credentials.clientid (resolveIasClientId). That is the same clientid tutorials-srv-mcp validates token aud against, so native-HTTP clients get the correct per-env id automatically — eliminating the wrong-env client_id failure class by construction. No IAS client is created; no secret or registration_access_token is minted (public client). The client's redirect_uris are echoed for the client↔proxy leg only (validated at /authorize); the proxy↔IAS leg always uses our fixed callback. If no identity binding is present, /register returns 500 (never guesses). Gated by the existing MCP_CONSENT_ENABLED flag. - approuter/lib/mcp-consent.js: REGISTER_PATH, resolveIasClientId(), handleRegister(), dispatch + exports - approuter/lib/well-known-oauth.js: advertise registration_endpoint under the flip - docs/end-users/mcp-quickstart.md + hugo/content/api-docs/_index.md: native-HTTP/DCR path now works (no client_id); reverse the stale "XSUAA does not support DCR" notes; mcp-remote + per-env client_id kept as the fallback - tests: +5 DCR (mcp-consent) +2 discovery (well-known); 60 green
feat(mcp): RFC 7591 Dynamic Client Registration for the consent proxy
Live DEV verification of #2710 (DCR) exposed the bug it was meant to kill, relocated into the proxy. POST /mcp-oauth/register returned cf2ea5eb… — the approuter's OWN tutorials-identity clientid — but tutorials-srv-mcp validates token `aud` against 0b1e8b56… (its separate tutorials-identity instance). A native-HTTP client registering via DCR would get cf2ea5eb…, complete login, and hit WrongAudience 401 at /mcp-auth/api — the same aud-mismatch class, just moved. Root cause: resolveIasClientId() trusted the approuter's VCAP identity binding, on the (false) assumption from #2593 that the approuter binds the SAME identity instance as srv-mcp. It does not — verified DEV 2026-10-11: - approuter → instance tutorials-approuter-identity, clientid cf2ea5eb… - srv-mcp → instance tutorials-identity, clientid 0b1e8b56… same tenant app_tid (3c6fa3f1…), distinct clients. @sap/xssec kind:ias checks aud === credentials.clientid exactly, so cf2ea5eb… cannot pass srv-mcp. Fix: resolveIasClientId() now prefers an explicit MCP_RESOURCE_CLIENT_ID env (srv-mcp's clientid, pinned per-env in the mtaext — DEV 0b1e8b56…, PROD 5a7cb5fd…), falling back to the VCAP binding only when unset. Deterministic; no shared-binding assumption. The DCR response is otherwise unchanged (public client, no secret, redirect_uris echoed for the client↔proxy leg only). - approuter/lib/mcp-consent.js: MCP_RESOURCE_CLIENT_ID precedence + corrected comment - deploy/dev.mtaext + deploy/prod.mtaext: pin srv-mcp's per-env clientid - tests: +3 (precedence over VCAP, /register returns the env value, empty-env falls back to VCAP); saveEnv tracks MCP_RESOURCE_CLIENT_ID; 63 green
…-clientid fix(mcp): DCR must return srv-mcp's clientid, not the approuter's own
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.
Release: MCP DCR + consent-proxy clientid fixes → PROD
Promotes the 3 MCP consent-proxy changes verified end-to-end on DEV. Scope is entirely MCP OAuth; no other subsystem touched.
Commits
docs(mcp)— correct per-env client_ids (DEV0b1e8b56…, PROD5a7cb5fd…are DISTINCT IAS clients)feat(mcp)— RFC 7591 Dynamic Client Registration for the consent proxy (/mcp-oauth/register)fix(mcp)— DCR must return srv-mcp's clientid, not the approuter's own (its VCAP identity binding is a different instance)Why
Native-HTTP OAuth MCP clients (Claude Code/Desktop, Joule Work Desktop) bootstrap via DCR. Before this, the consent proxy had no
/register, so the advertised "native HTTP, no bridge" path failed — the only working path was the mcp-remote bridge with an explicit, env-specific client_id. DCR now hands clients the correct per-env clientid automatically, eliminating the wrong-envaud-mismatch failure class (the multi-day PROD saga) by construction.DEV verification (2026-10-11)
POST /mcp-oauth/register→ 201,client_id = 0b1e8b56…(srv-mcp's, not the approuter'scf2ea5eb…), no secret.mcp-remote(no--static-oauth-client-info): discovery → DCR → consent → IAS login → token → Connected, no WrongAudience 401.PROD config
deploy/prod.mtaextpinsMCP_RESOURCE_CLIENT_ID: 5a7cb5fd-a0f0-4678-8f51-f8c471e0ab34(PROD srv-mcp's clientid). The PROD IAS client5a7cb5fd…already hashttps://developers.sap.com/mcp-oauth/callbackregistered (done during the earlier saga). No new secrets;MCP_CONSENT_STATE_SECRETalready seeded in PROD credstore.🤖 Generated with Claude Code