Skip to content

feat(lightspeed): add MCP servers settings panel#2657

Open
ciiay wants to merge 17 commits intoredhat-developer:mainfrom
ciiay:rhidp-12079-mcp-token-config-2
Open

feat(lightspeed): add MCP servers settings panel#2657
ciiay wants to merge 17 commits intoredhat-developer:mainfrom
ciiay:rhidp-12079-mcp-token-config-2

Conversation

@ciiay
Copy link
Copy Markdown
Member

@ciiay ciiay commented Apr 1, 2026

Hey, I just made a Pull Request!

For RHIDP-12079

✔️ Checklist

  • A changeset describing the change and affected packages. (more info)
  • Added or Updated documentation
  • Tests for new functionality and regression tests for bug fixes
  • Screenshots attached (for UI changes)

Screen recording:

rhidp_12079.mp4

@rhdh-gh-app
Copy link
Copy Markdown

rhdh-gh-app bot commented Apr 1, 2026

Important

This PR includes changes that affect public-facing API. Please ensure you are adding/updating documentation for new features or behavior.

Changed Packages

Package Name Package Path Changeset Bump Current Version
@red-hat-developer-hub/backstage-plugin-lightspeed-backend workspaces/lightspeed/plugins/lightspeed-backend minor v1.4.0
@red-hat-developer-hub/backstage-plugin-lightspeed workspaces/lightspeed/plugins/lightspeed minor v1.4.0

ciiay added 15 commits April 3, 2026 11:24
Signed-off-by: Yi Cai <yicai@redhat.com>
Signed-off-by: Yi Cai <yicai@redhat.com>
Signed-off-by: Yi Cai <yicai@redhat.com>
Signed-off-by: Yi Cai <yicai@redhat.com>
Signed-off-by: Yi Cai <yicai@redhat.com>
Signed-off-by: Yi Cai <yicai@redhat.com>
Signed-off-by: Yi Cai <yicai@redhat.com>
Signed-off-by: Yi Cai <yicai@redhat.com>
Signed-off-by: Yi Cai <yicai@redhat.com>
Signed-off-by: Yi Cai <yicai@redhat.com>
Signed-off-by: Yi Cai <yicai@redhat.com>
Implement WIP token configuration modal behaviors for MCP servers, including saved-token revisit, debounced validation feedback, and status-specific UI states to unblock frontend integration work.

Made-with: Cursor
Signed-off-by: Yi Cai <yicai@redhat.com>
@ciiay ciiay force-pushed the rhidp-12079-mcp-token-config-2 branch from b75aef3 to 23e4633 Compare April 3, 2026 16:42
@ciiay ciiay marked this pull request as ready for review April 3, 2026 16:43
@rhdh-qodo-merge
Copy link
Copy Markdown

Review Summary by Qodo

Add MCP servers settings panel with token configuration and validation

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Add MCP servers settings panel with token configuration UI
• Implement debounced token validation with inline feedback
• Support dual auth header formats (raw token and Bearer prefix)
• Add backend endpoints for server management and validation
• Integrate settings modal into chat interface with fullscreen support
Diagram
flowchart LR
  A["User opens MCP settings"] --> B["Load configured servers"]
  B --> C["Display servers table"]
  C --> D["User edits server token"]
  D --> E["Debounced validation"]
  E --> F["Show success/error feedback"]
  F --> G["User saves token"]
  G --> H["Backend persists token"]
  H --> I["Validate server connection"]
Loading

Grey Divider

File Changes

1. workspaces/lightspeed/plugins/lightspeed-backend/src/service/mcp-server-validator.ts ✨ Enhancement +121/-20

Enhanced token validation with dual auth header support

workspaces/lightspeed/plugins/lightspeed-backend/src/service/mcp-server-validator.ts


2. workspaces/lightspeed/plugins/lightspeed-backend/src/service/mcp-server-validator.test.ts 🧪 Tests +77/-0

Add tests for auth header retry logic

workspaces/lightspeed/plugins/lightspeed-backend/src/service/mcp-server-validator.test.ts


3. workspaces/lightspeed/plugins/lightspeed-backend/__fixtures__/mcpHandlers.ts 🧪 Tests +4/-1

Update mock handler to accept raw tokens

workspaces/lightspeed/plugins/lightspeed-backend/fixtures/mcpHandlers.ts


View more (11)
4. workspaces/lightspeed/plugins/lightspeed-backend/src/service/mcp-server.test.ts 🧪 Tests +2/-2

Update test expectations for raw token validation

workspaces/lightspeed/plugins/lightspeed-backend/src/service/mcp-server.test.ts


5. workspaces/lightspeed/plugins/lightspeed-backend/src/service/notebooks/sessions/sessionService.test.ts Formatting +1/-1

Remove unnecessary type annotation

workspaces/lightspeed/plugins/lightspeed-backend/src/service/notebooks/sessions/sessionService.test.ts


6. workspaces/lightspeed/plugins/lightspeed-backend/README.md 📝 Documentation +19/-1

Document MCP server management endpoints

workspaces/lightspeed/plugins/lightspeed-backend/README.md


7. workspaces/lightspeed/plugins/lightspeed/README.md 📝 Documentation +19/-0

Document MCP settings panel and token validation behavior

workspaces/lightspeed/plugins/lightspeed/README.md


8. workspaces/lightspeed/plugins/lightspeed/package.json Dependencies +1/-0

Add PatternFly React Table dependency

workspaces/lightspeed/plugins/lightspeed/package.json


9. workspaces/lightspeed/plugins/lightspeed/src/components/McpServersSettings.tsx ✨ Enhancement +1159/-0

Implement MCP servers settings panel with token management

workspaces/lightspeed/plugins/lightspeed/src/components/McpServersSettings.tsx


10. workspaces/lightspeed/plugins/lightspeed/src/components/McpSettingsIcon.tsx ✨ Enhancement +34/-0

Add custom MCP settings icon component

workspaces/lightspeed/plugins/lightspeed/src/components/McpSettingsIcon.tsx


11. workspaces/lightspeed/plugins/lightspeed/src/components/LightspeedChatBoxHeader.tsx ✨ Enhancement +11/-0

Add MCP settings button to chat header menu

workspaces/lightspeed/plugins/lightspeed/src/components/LightspeedChatBoxHeader.tsx


12. workspaces/lightspeed/plugins/lightspeed/src/components/LightspeedChat.tsx ✨ Enhancement +195/-69

Integrate MCP settings panel with fullscreen layout support

workspaces/lightspeed/plugins/lightspeed/src/components/LightspeedChat.tsx


13. workspaces/lightspeed/.changeset/sixty-chefs-refuse.md 📝 Documentation +13/-0

Add changeset for MCP servers settings feature

workspaces/lightspeed/.changeset/sixty-chefs-refuse.md


14. workspaces/lightspeed/plugins/lightspeed/src/components/LightSpeedChat.tsx Additional files +195/-69

...

workspaces/lightspeed/plugins/lightspeed/src/components/LightSpeedChat.tsx


Grey Divider

Qodo Logo

@rhdh-qodo-merge
Copy link
Copy Markdown

rhdh-qodo-merge bot commented Apr 3, 2026

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX Issues (0)

Grey Divider


Action required

1. Cannot forget MCP token 🐞 Bug ≡ Correctness
Description
In McpServersSettings, clicking “Forget token” only clears local state and the Save button is
disabled when the token input is empty, so users cannot persistently remove a previously saved token
(i.e., submit token:null). This leaves users stuck with stored credentials they cannot delete via
the UI.
Code

workspaces/lightspeed/plugins/lightspeed/src/components/McpServersSettings.tsx[R1122-1145]

+            <Button
+              key="save"
+              variant="primary"
+              onClick={() => void saveServerToken()}
+              isDisabled={
+                !canManageMcp ||
+                Boolean(isSaving[editingServer?.name ?? '']) ||
+                tokenValidationState === 'validating' ||
+                !tokenInputValue.trim()
+              }
+              className={classes.modalActionButton}
+            >
+              Save
+            </Button>
+            {hasSavedTokenInModal && (
+              <Button
+                key="forget-token"
+                variant="plain"
+                onClick={forgetSavedToken}
+                className={classes.forgetTokenButton}
+              >
+                Forget token
+              </Button>
+            )}
Evidence
The modal disables Save when the token is empty, and the “Forget token” handler does not call the
backend PATCH endpoint. Meanwhile, both the frontend save flow and backend store explicitly support
clearing a token by sending token: null, making this a functional bug (supported capability is
unreachable from UI).

workspaces/lightspeed/plugins/lightspeed/src/components/McpServersSettings.tsx[1122-1145]
workspaces/lightspeed/plugins/lightspeed/src/components/McpServersSettings.tsx[792-798]
workspaces/lightspeed/plugins/lightspeed/src/components/McpServersSettings.tsx[854-873]
workspaces/lightspeed/plugins/lightspeed-backend/src/service/mcp-server-store.ts[110-138]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Users cannot delete a previously saved MCP token from the settings modal. The UI disables the Save button when the token field is empty, and the “Forget token” button only clears local component state without persisting `token: null` to the backend.

## Issue Context
Backend persistence supports clearing tokens by sending `token: null` (store upsert preserves null and resets status). The frontend already builds a PATCH payload that would send `token: null`, but the Save button is disabled when the input is empty, making the token-removal path unreachable.

## Fix Focus Areas
- workspaces/lightspeed/plugins/lightspeed/src/components/McpServersSettings.tsx[792-798]
- workspaces/lightspeed/plugins/lightspeed/src/components/McpServersSettings.tsx[1122-1131]
- workspaces/lightspeed/plugins/lightspeed/src/components/McpServersSettings.tsx[854-873]

## Suggested fix
- Make “Forget token” actually persist the deletion by calling `patchServer(editingServer.name, { token: null })` (and optionally re-validate / close modal).
- Alternatively (or additionally), allow Save when clearing a token (e.g., only require non-empty input when creating/updating a token, but allow empty to mean delete), so `saveServerToken()` can submit `token: null`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Token save forces enable 🐞 Bug ≡ Correctness
Description
saveServerToken always patches { enabled: true } along with the token, which re-enables a server
even if the user previously disabled it. This makes token edits change server enabled state
unexpectedly.
Code

workspaces/lightspeed/plugins/lightspeed/src/components/McpServersSettings.tsx[R868-872]

+    try {
+      await patchServer(editingServer.name, {
+        enabled: true,
+        token: hasToken ? token : null,
+      });
Evidence
The UI always sends enabled: true when saving a token, and the backend PATCH endpoint persists the
provided enabled value via settingsStore.upsert. Therefore a disabled server will become enabled
as a side effect of token changes.

workspaces/lightspeed/plugins/lightspeed/src/components/McpServersSettings.tsx[854-873]
workspaces/lightspeed/plugins/lightspeed-backend/src/service/router.ts[340-351]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Saving a token in the MCP configure modal always sends `enabled: true` to the backend, which can unintentionally re-enable a server that the user had disabled.

## Issue Context
The backend PATCH handler persists `enabled` when provided. Token edits should not implicitly change enabled state unless the user explicitly toggles it.

## Fix Focus Areas
- workspaces/lightspeed/plugins/lightspeed/src/components/McpServersSettings.tsx[854-873]
- workspaces/lightspeed/plugins/lightspeed-backend/src/service/router.ts[340-351]

## Suggested fix
- In `saveServerToken`, omit the `enabled` field entirely when updating only the token, or send `enabled: editingServer.enabled`.
- Keep enable/disable exclusively driven by the row toggle (or a dedicated control), not as a side effect of token saves.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Implicit any test service🐞 Bug ⚙ Maintainability
Description
sessionService.test.ts changes let service: SessionService; to let service;, removing type
checking and weakening test safety. Since Lightspeed’s workspace tsconfig includes plugins/*/src,
this test file is in the typechecked set and should remain properly typed.
Code

workspaces/lightspeed/plugins/lightspeed-backend/src/service/notebooks/sessions/sessionService.test.ts[35]

+  let service;
Evidence
The test now declares service without a type, and the Lightspeed workspace tsconfig includes
plugin src directories, which is where this test lives, so it is part of the workspace TypeScript
surface area and benefits from maintaining explicit types.

workspaces/lightspeed/plugins/lightspeed-backend/src/service/notebooks/sessions/sessionService.test.ts[27-49]
workspaces/lightspeed/tsconfig.json[1-18]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A backend test now uses an implicitly-typed `any` variable (`let service;`) instead of `let service: SessionService;`, reducing type safety and increasing the chance of unnoticed test breakage.

## Issue Context
The test file is under `workspaces/lightspeed/plugins/.../src`, which is included by the Lightspeed workspace tsconfig.

## Fix Focus Areas
- workspaces/lightspeed/plugins/lightspeed-backend/src/service/notebooks/sessions/sessionService.test.ts[27-49]

## Suggested fix
- Change `let service;` back to `let service: SessionService;` (or initialize with `let service = new SessionService(...)` in a way that preserves type inference without implicit any).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines +1122 to +1145
<Button
key="save"
variant="primary"
onClick={() => void saveServerToken()}
isDisabled={
!canManageMcp ||
Boolean(isSaving[editingServer?.name ?? '']) ||
tokenValidationState === 'validating' ||
!tokenInputValue.trim()
}
className={classes.modalActionButton}
>
Save
</Button>
{hasSavedTokenInModal && (
<Button
key="forget-token"
variant="plain"
onClick={forgetSavedToken}
className={classes.forgetTokenButton}
>
Forget token
</Button>
)}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Cannot forget mcp token 🐞 Bug ≡ Correctness

In McpServersSettings, clicking “Forget token” only clears local state and the Save button is
disabled when the token input is empty, so users cannot persistently remove a previously saved token
(i.e., submit token:null). This leaves users stuck with stored credentials they cannot delete via
the UI.
Agent Prompt
## Issue description
Users cannot delete a previously saved MCP token from the settings modal. The UI disables the Save button when the token field is empty, and the “Forget token” button only clears local component state without persisting `token: null` to the backend.

## Issue Context
Backend persistence supports clearing tokens by sending `token: null` (store upsert preserves null and resets status). The frontend already builds a PATCH payload that would send `token: null`, but the Save button is disabled when the input is empty, making the token-removal path unreachable.

## Fix Focus Areas
- workspaces/lightspeed/plugins/lightspeed/src/components/McpServersSettings.tsx[792-798]
- workspaces/lightspeed/plugins/lightspeed/src/components/McpServersSettings.tsx[1122-1131]
- workspaces/lightspeed/plugins/lightspeed/src/components/McpServersSettings.tsx[854-873]

## Suggested fix
- Make “Forget token” actually persist the deletion by calling `patchServer(editingServer.name, { token: null })` (and optionally re-validate / close modal).
- Alternatively (or additionally), allow Save when clearing a token (e.g., only require non-empty input when creating/updating a token, but allow empty to mean delete), so `saveServerToken()` can submit `token: null`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Signed-off-by: Yi Cai <yicai@redhat.com>
Signed-off-by: Yi Cai <yicai@redhat.com>
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 3, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant