feat(lightspeed): add DCR authentication support for MCP servers#3347
feat(lightspeed): add DCR authentication support for MCP servers#3347maysunfaisal wants to merge 1 commit into
Conversation
Co-authored-by: Cursor <cursoragent@cursor.com>
|
Important This PR includes changes that affect public-facing API. Please ensure you are adding/updating documentation for new features or behavior. Changed Packages
|
|
gabemontero
left a comment
There was a problem hiding this comment.
hey @maysunfaisal - so claude and I looked at two error scenarios:
- If the user's RBAC policy denies a specific tool invocation
for this, claude's analysis was that the rejection happens inside @backstage/plugin-mcp-actions-backend, not in this code. Lightspeed streams back whatever LCS returns — so the user would see whatever error or refusal the LCS/MCP Actions layer produces in the chat stream. The Lightspeed backend is fully opaque to per-tool authorization outcomes.
Assuming this is correct, I'm curious if it makes sense to catch the LCS/MCP actions layer error and display a potentially more user friendly indication of permission issues.
WDYT?
- Unexpected error minting a Backstage token (
getPluginRequestTokenthrows)
Claude claims the entire chat query fails (I'll post the details in a moment). It then goes on that is a chat query results in querying multiple MCP servers, none of those servers gets called.
I suppose a user prompt could result in multiple queries, but even if so, it seems unpredictable whether calling the other mcp servers is productive i.e. how dependent would the output of the backstage mcp server be.
I'm inclined to leave this be, but thought I would surface it in the review as due diligence to get your and everyone else's take.
Here is the code analysis from claude on gitPluginRequestToken
There are two call sites for getPluginRequestToken, and neither has a local try/catch around it:
A) During /v1/query (chat flow) — buildMcpHeaders() calls getPluginRequestToken at ~line 133. If it throws, the exception propagates unhandled out of buildMcpHeaders and is caught by the outer catch in the /v1/query handler (~line 775):
} catch (error) {
const errormsg = `Error fetching completions from ${provider}: ${error}`;
logger.error(errormsg);
response.status(500).json({ error: errormsg });
}
The entire chat query fails with a 500. Even if only one of several MCP servers uses auth: dcr, a token-minting failure for that one server aborts the whole request — the error is not isolated per-server. The other MCP servers (static-token or other DCR servers) never get their headers built.
B) During POST /mcp-servers/:name/validate (~line 393) — same pattern: no local catch, the outer handler returns 500 with "Validation failed".
Note: there is a guard for when authService/credentials are absent (logs a warning, skips the server), but that only handles the case where the services weren't injected — not a runtime failure in getPluginRequestToken itself.



Hey, I just made a Pull Request!
✔️ Checklist
Issue
https://redhat.atlassian.net/browse/RHIDP-11657
Summary
Adds Dynamic Client Registration (DCR) authentication for MCP servers in Lightspeed, allowing the backend to mint per-user plugin request tokens instead of requiring static tokens.
What changed
Backend (
lightspeed-backend)auth: dcrconfig option for MCP servers — when set, the backend mints a Backstage service token on behalf of the user viagetPluginRequestTokenAuthServiceinjection into the routerGET /mcp-serversandPATCH /mcp-servers/:nameresponses now include theauthfieldhasToken: truealways (tokens are minted per-request, no manual entry needed)buildMcpHeaderssends the minted token inMCP-HEADERSfor DCR serversFrontend (
lightspeed)Bug fixes along the way
@patternfly/react-coreversions (added resolution to force6.4.3)attachButtonPositionprop that no longer exists in@patternfly/chatbot@backstage/plugin-permission-backendregistered separately (breaking change from v5/v6)Other
@backstage/plugin-authto frontend for DCR OAuth2 consent pagedist-dynamicto.prettierignorerbac-policy.csvwith Lightspeed permissions for local RBAC testingHow to test
cd workspaces/lightspeed && yarn test:all(769 tests pass)@backstage/plugin-mcp-actions-backendadded toindex.tsexperimentalDynamicClientRegistration.enabled: trueinapp-config.yamlmcpServers: [{ name: "...", auth: dcr }]in lightspeed confighttp://localhost:7007/api/mcp-actions/v1— DCR OAuth consent should pop up in browserauth: dcrinvalues.yamlunderlightspeed.mcpServersConfig example